I'm working through Joe Armstrong's Programming Erlang 2nd E. The book has exercises at the end of each chapter. Chapter 13, exercise 1 says:
Write a function
my_spawn(Mod, Func, Args)
that behaves likespawn(Mod, Func, Args)
but with one difference. If the spawned process dies, a message should be printed saying why the process died and how long the process lived for before it died.
Here's a solution that has a race condition:
my_spawn(Mod, Func, Args) ->
Pid = spawn(Mod, Func, Args),
spawn(fun() ->
Ref = monitor(process, Pid),
T1 = erlang:monotonic_time(millisecond),
receive
{'DOWN', Ref, process, Pid, Why} ->
io:format("~p died because of ~p~n", [Pid, Why]),
io:format("~p lived for ~p ms~n", [Pid, erlang:monotonic_time(millisecond) - T1])
end
end),
Pid.
Spawning the process and creating the monitor is not an atomic step, so if the process dies after spawning but before the monitor is created, we won't get the error message.
Here's an attempt without the race condition:
my_spawn_atomic(Mod, Func, Args) ->
spawn(fun() ->
{Pid, Ref} = spawn_monitor(Mod, Func, Args),
T1 = erlang:monotonic_time(millisecond),
receive {'DOWN', Ref, process, Pid, Why} ->
io:format("~p died because of ~p~n", [Pid, Why]),
io:format("~p lived for ~p ms~n", [Pid, erlang:monotonic_time(millisecond) - T1])
end
end).
But the PID this returns is that of the monitoring process, not the Func
process. And given that spawn
always returns the PID of the process it creates, there doesn't seem to be a way to return Pid
without resorting to a side effect.
What's the idiomatic way to do implement the atomic spawning?
spawn_link
. See also stackoverflow.com/q/28531101/409228 . – Steve Vinoskispawn_link
help? I'm already usingspawn_monitor
. – Tianxiang Xiong