我得到了以下设置:
当我在alice@usa.local上启动Alice(alice:start/0
)时,它会在gca.local上生成链接的Bob(bob:start/1
)。这两个处理都是陷阱退出。
当Alice死于某事时,Bob会收到通知并继续运行。 当Bob死于某事时,Alice会收到通知并继续运行。
当我切断网络连接时,Alice会收到Bob已经死于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.
答案 0 :(得分:2)
问题是io:format/2
调用bob.erl的第13行。在spawn_link('bob@gca.local',...
中创建新流程后,它会继承alice
流程的组长,这是alice@usa.local
的本地流程,因此您将在{{1}上看到bob
的所有输出}} 终奌站。 alice@usa.local
断开时alice@usa.local
处理bob
第12行的EXIT
消息,但第13行的bob.erl
电话失败,因为组长已断开连接。
快速解决方法是将所有bob的io:format/2
来电更改为io:format/2
。在这种情况下,所有bob的输出都将显示在io:format(user, Format, Data)
终端上。
然而,在实际项目中,你真的应该使用gen_server行为,因为它处理许多粗略的情况,特别是对于节点间通信(不要忘记查看代码)。此外,您确实需要在此使用monitor/2或/和monitor_node/2代替bob@gca.local
和link
。
答案 1 :(得分:-1)
每当我在代码中看到trap_exit
时,我都会假设某人重新发明了OTP的某些部分。这似乎就是这种情况。
查看distributed applications文档。这样做只需要配置就可以了。
我已经使用了它大约7年的成功(目前在原子盒和arm5盒之间)。