Как стать автором
Обновить

Комментарии 11

А почему он должен падать? В первом случае он упал потому как был слинкован с упавшим процессом, а во втором у него выставлен trap_exit.
Согласно документации, получение kill — немедленная и безоговорочная смерть.
www.erlang.org/doc/reference_manual/processes.html
When a process is trapping exits, it will not terminate when an exit signal is received. Instead, the signal is transformed into a message {'EXIT',FromPid,Reason} which is put into the mailbox of the process just like a regular message.

An exception to the above is if the exit reason is kill, that is if exit(Pid,kill) has been called. This will unconditionally terminate the process, regardless of if it is trapping exit signals or not.
Да, я неправ. Прошу прощения.
Оболочка получила сигнал {'EXIT',<0.44.0>,kill}, но не завершила свою работу!

Вообще, у оболочки (модуль erl_eval) есть несколько отличий от реальных процессов и модулей. Об этом редко пишут, да натыкаются тоже не часто. Думаю, что ответ кроется где-то в исходниках.
Вот примеры из последнего, на что натыкался:
Передача fun на другие ноды
Особенности bit syntax
Сейчас подумал, что разница в том, что процесс умирает от сигнала, а не от сообщения. А если включен trapping, то сингал преобразуется в сообщение. Таким образом не выходит суицида от self()!{'EXIT', self(), kill}. Однако exit(self(), kill) работает.
Не зря ж в документации сказано Instead, the signal is transformed into a message {'EXIT',FromPid,Reason} which is put into the mailbox of the process just like a regular message.
Вот немного тестов в консоли.
Спаунится прилинкованный процесс, который ждёт 15 секунд и выходит.
1> spawn_link(erlang, apply, [fun(Parent)-> timer:sleep(15000), io:format("finish~n", []) end, [self()]]).
<0.35.0>
finish


Процесс запускается, но тут же убивается. Текущий прилинкованный процесс консоли умирает.
2> exit(spawn_link(erlang, apply, [fun(Parent)-> timer:sleep(15000), io:format("finish~n", []) end,[self()]]),kill).
** exception exit: killed


Вешаю trap_exit и повторяю
3> process_flag(trap_exit, true).
false
4> exit(spawn_link(erlang, apply, [fun(Parent)-> timer:sleep(15000), io:format(«finish~n», []) end, [self()]]),kill).
true
5> receive X->X end.
{'EXIT',<0.41.0>,killed}

Действительно, получается, что trap_exit преобразует сигнал о смерти прилинкованного процесса в обычное сообщение, даже если это был kill. То есть сам процесс будет убит в любом случае, а вот приликованные процессы уже получают не kill, a killed.

Сделал вообще наркоманский тест. Спауню процесс, который спаунит ещё один процесс, линкуется к нему и убивает. В итоге выживает только первый.
9> spawn(erlang, apply, [fun(Pair)-> process_flag(trap_exit, true), link(Pair), exit(Pair, kill), timer:sleep(1000), io:format("finish pair~n", []) end, [spawn(erlang, apply, [fun(Parent)-> process_flag(trap_exit, true), timer:sleep(15000), io:format("finish~n", []) end, [self()]])]]).
<0.52.0>
finish pair


Возвращаясь к исходному вопросу, получаем ответ, что оболочка осталась жива, ибо получила сигнал не о своей смерти, а о чужой. Так что всё ОК и особенности оболочки тут не причём.
Наверное, оно и логично: иначе по дереву супервизии прокатился бы брутал-килл и ничего не осталось бы.
Как раз для того, чтобы брутал-килл не прокатился сообщение трансформируется в из kill -> killed. А в последнем примере оно не трансформировалось.
Возможно вы правы. Надо будет на досуге покопаться в исходниках.
Про передачу функции на другие ноды читал, там есть хорошая ссылка на статью. Надо пожалуй её опубликовать.
Всем, кому интересно, есть фреймворк на Java и Scala, который взял в себя лучшее от Erlang, при этом оставаясь в рамках «традиционных» языков:
akka.io
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории