erlang的EXIT和DOWN信号

时间:2012-11-18 21:49:39

标签: erlang rabbitmq exit supervisor

以下代码也来自rabbitmq's supervisor2.erl。代码的功能是为每个孩子杀死主管的孩子:

  1. 监视子项发送可捕获的退出信号

  2. 启动计时器

  3. 如果计时器到达,发送一个无法解决的退出信号(杀死)。

  4. 关于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.
    

1 个答案:

答案 0 :(得分:1)

你有两件事令人困惑:

  • 首先,孩子是陷阱退出,但你正在看管理员代码。孩子对退出信号的处理方式不会直接影响主管。
  • kill退出信号无法被困。它总是杀死孩子。

supervisor2在孩子身上有一个监视器。这意味着它可以保证获得'DOWN'消息,并且此代码关注获取此类消息。如果supervisor2也捕获退出,则会另外收到'EXIT'消息。