сигнал EXIT и DOWN от erlang

Следующий код также взят из rabbitmq's supervisor2.erl. Функция кода состоит в том, чтобы убить дочерних элементов супервизора для каждого дочернего элемента:

  1. контролировать ребенка, отправить перехватываемый сигнал выхода

  2. запуск таймера

  3. если таймер прибудет, пошлите неперехватываемый сигнал выхода (убийство).

Мой вопрос о 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.

person Chen Yu    schedule 18.11.2012    source источник


Ответы (1)


Здесь вы путаете две вещи:

  • Во-первых, ребенок перехватывает выходы, но вы смотрите на код супервизора. То, что ребенок делает с сигналами на выход, не влияет напрямую на супервайзера.
  • сигнал выхода kill не может быть перехвачен. Это всегда убивает ребенка.

У supervisor2 есть монитор на ребенке. Это означает, что гарантированно будет получено сообщение 'DOWN', и этот код обеспокоен получением сообщения такого типа. Если supervisor2 также перехватывает выходы, он дополнительно получит сообщение 'EXIT'.

person I GIVE CRAP ANSWERS    schedule 19.11.2012
comment
Что касается вашего последнего абзаца, вы уверены, почему сигнал «ВНИЗ» будет следовать за сигналом «ВЫХОД»? Почему сигнал «ВЫХОД» не следует за сигналом «ВНИЗ»? Почему? Я сделал пометку в приведенном выше коде, он показывает строгую последовательность сигналов. - person Chen Yu; 20.11.2012