Code
erlang
-module(keeper).
-export([start/0, child/0]).
start() ->
process_flag(trap_exit, true), % convert EXIT signals to messages
Pid = spawn_link(fun child/0), % spawn AND link atomically
keeper_loop(Pid).
keeper_loop(Pid) ->
receive
{'EXIT', Pid, Reason} ->
io:format("child died with ~p, restarting~n", [Reason]),
NewPid = spawn_link(fun child/0),
keeper_loop(NewPid);
{'EXIT', _Other, _Reason} ->
%% some other linked process died; ignore
keeper_loop(Pid);
{stop, From} ->
exit(Pid, shutdown),
From ! ok
end.
child() ->
timer:sleep(rand:uniform(5000)),
case rand:uniform(3) of
1 -> erlang:error(bad_thing); % crash on purpose
2 -> exit(normal); % 'normal' exits don't propagate
_ -> exit(bad_luck) % abnormal exit
end.
% With trap_exit=true the keeper survives all of these because
% exit signals arrive as {'EXIT', Pid, Reason} messages.