以下代码也来自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.
答案 0 :(得分:1)
你有两件事令人困惑:
kill
退出信号无法被困。它总是杀死孩子。 supervisor2
在孩子身上有一个监视器。这意味着它可以保证获得'DOWN'
消息,并且此代码关注获取此类消息。如果supervisor2
也捕获退出,则会另外收到'EXIT'
消息。