Следующий код также взят из rabbitmq's supervisor2.erl
. Функция кода состоит в том, чтобы убить дочерних элементов супервизора для каждого дочернего элемента:
контролировать ребенка, отправить перехватываемый сигнал выхода
запуск таймера
если таймер прибудет, пошлите неперехватываемый сигнал выхода (убийство).
Мой вопрос о EXIT and DOWN signal.
Если ребенок не перехватывает сигнал выхода, супервизор получит 2 сигнала, сначала сигнал exit
, а затем сигнал DOWN
, правильно? Является ли последовательность сигналов строго гарантированной?
Если ребенок перехватит сигнал exit
, супервизор получит только 1 сигнал, только сигнал down
, верно?
terminate_simple_children(Child, Dynamics, SupName) ->
Pids = dict:fold(fun (Pid, _Args, Pids) ->
erlang:monitor(process, Pid),
unlink(Pid),
exit(Pid, child_exit_reason(Child)),
[Pid | Pids]
end, [], Dynamics),
TimeoutMsg = {timeout, make_ref()},
TRef = timeout_start(Child, TimeoutMsg),
{Replies, Timedout} =
lists:foldl(
fun (_Pid, {Replies, Timedout}) ->
{Reply, Timedout1} =
receive
TimeoutMsg ->
Remaining = Pids -- [P || {P, _} <- Replies],
[exit(P, kill) || P <- Remaining],
receive {'DOWN', _MRef, process, Pid, Reason} ->
{{error, Reason}, true}
end;
{'DOWN', _MRef, process, Pid, Reason} ->
{child_res(Child, Reason, Timedout), Timedout};
{'EXIT', Pid, Reason} -> %%<==== strict signal, first EXIT, then DOWN.
receive {'DOWN', _MRef, process, Pid, _} ->
{{error, Reason}, Timedout}
end
end,
{[{Pid, Reply} | Replies], Timedout1}
end, {[], false}, Pids),
timeout_stop(Child, TRef, TimeoutMsg, Timedout),
ReportError = shutdown_error_reporter(SupName),
[case Reply of
{_Pid, ok} -> ok;
{Pid, {error, R}} -> ReportError(R, Child#child{pid = Pid})
end || Reply <- Replies],
ok.