Links, Monitors & Fault Tolerance
When a process terminates abnormally, an exit signal is sent to all linked processes, which also die — unless they trap exits.
25.1 Links — bidirectional
When a process terminates abnormally, an exit signal is sent to all linked processes, which also die — unless they trap exits.
Pid = spawn_link(fun() -> exit(crash) end), % atomically spawn + link
link(Pid), unlink(Pid).25.2 Trapping exits
process_flag(trap_exit, true),
Pid = spawn_link(fun() -> exit(boom) end),
receive
{'EXIT', Pid, Reason} -> io:format("Child exited: ~p~n", [Reason])
end.25.3 Exit signal semantics
{'EXIT', Pid, normal} message kill (via exit(Pid, kill)) dies with reason killed dies anyway (untrappable) dies with same reason {'EXIT', Pid, Reason} message
exit(Pid, shutdown), % send an exit signal to another process
exit(Pid, kill). % brutal kill25.4 Monitors — unidirectional
Monitors stack (multiple monitors → multiple DOWN messages) and don't affect the monitored process. Use monitors when you just want to *know*; use links when processes should *live and die together*.
Ref = monitor(process, Pid),
receive
{'DOWN', Ref, process, Pid, Reason} -> {down, Reason}
end,
demonitor(Ref, [flush]),
{Pid2, Ref2} = spawn_monitor(fun() -> ok end).25.5 Aliases (OTP 24+)
Prevents stray late replies after timeouts.
Alias = alias([reply]), % reply-only address, auto-deactivates after one reply
Server ! {request, Alias},
receive {Alias, Reply} -> Reply end.25.6 Let it crash & the error kernel
Separate worker code (does the job, may crash) from supervisor code (restarts workers).
Don't catch everything defensively — crash, log, and restart in a clean state.
Keep the critical state (the error kernel) small and well-protected.