次のコードもrabbitmq's supervisor2.erl
. コードの機能は、すべての子に対して、スーパーバイザーの子を殺すことです。
子を監視して、トラップ可能な終了信号を送信します
タイマーを開始
タイマーが到着したら、トラップ不能な終了シグナル (kill) を送信します。
についての私の質問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.