Erlang процесс умирает после отключения - PullRequest
0 голосов
/ 15 августа 2011

У меня есть следующие настройки:

  • 2 Серверы с fqdn usa.local и gca.local
  • 1 erlang-узел на каждом из них с именем alice@usa.local и bob@ gca.local

Когда я запускаю Алису (alice:start/0) на alice@usa.local, она порождает связанного Боба (bob:start/1) на gca.local.Обе обработки являются ловушечными выходами.

Когда Алиса что-то умирает, Боб получает уведомление и продолжает работать.Когда Боб умирает от чего-то, Алиса получает уведомление и продолжает работать.

Когда я разрываю сетевое соединение, Алиса получает уведомление о том, что Боб умер от noconnection, и процесс bob умирает на bob@gca.local.

Я не хочу, чтобы это произошло.Я хочу, чтобы Боб продолжал работать, хотя он теряет связь с Алисой.

Мои вопросы:

  • Имеет ли это что-то, что я изначально породил Боба изузел Алисы?
  • Как я могу заставить Боба пережить потерю соединения?

Вот код:

-module (alice).
-compile (export_all).

start () ->
    register (alice, spawn (fun init/0) ).

stop () ->
    whereis (alice) ! stop.

init () ->
    process_flag (trap_exit, true),
    Bob = spawn_link ('bob@gca.local', bob, start, [self () ] ),
    loop (Bob).

loop (Bob) ->
    receive
        stop -> ok;
        {'EXIT', Bob, Reason} ->
            io:format ("Bob died of ~p.~n", [Reason] ),
            loop (Bob);
        Msg ->
            io:format ("Alice received ~p.~n", [Msg] ),
            loop (Bob)
    end.

-module (bob).
-compile (export_all).

start (Alice) ->
    process_flag (trap_exit, true),
    register (bob, self () ),
    loop (Alice).

loop (Alice) ->
    receive
        stop -> ok;
        {'EXIT', Alice, Reason} ->
            io:format ("Alice died of ~p.~n", [Reason] ),
            loop (Alice);
        Msg ->
            io:format ("Bob received ~p.~n", [Msg] ),
            loop (Alice)
    after 5000 ->
        Alice ! "Hi, this Bob",
        loop (Alice)
    end.

Ответы [ 2 ]

2 голосов
/ 18 августа 2011

Проблема в io:format/2 вызове по линии 13 bob.erl.Когда новый процесс создается в spawn_link('bob@gca.local',..., он наследует лидера группы процесса alice, который является локальным для alice@usa.local процесса, поэтому вы увидите все выходные данные из терминала bob на alice@usa.local.Когда alice@usa.local отключен, bob обрабатывает EXIT сообщение в строке 12 из bob.erl, но io:format/2 вызов по линии 13 не удался, потому что лидер группы был отключен.

Быстрое решение состоит в том, чтобы изменить всеБоб io:format/2 звонит на io:format(user, Format, Data).В этом случае весь вывод bob будет отображаться на терминале bob@gca.local.

Однако в реальных проектах вам действительно следует использовать поведение gen_server , потому что оно обрабатывает множество грубых случаев, особенно для межузловой связи.(не забудьте посмотреть код).Более того, вам действительно нужно использовать monitor / 2 или / и monitor_node / 2 вместо link и trap_exit здесь.

0 голосов
/ 15 августа 2011

Всякий раз, когда я вижу код trap_exit, я предполагаю, что кто-то заново изобретает какую-то часть OTP.Похоже, что так и есть.

Посмотрите документацию по распределенным приложениям .Это делает то, что вы хотите в простой конфигурации.

Я использовал его с довольно большим успехом уже около 7 лет (в настоящее время между блоком атомов и блоком arm5).

...