我正在阅读Programming Erlang! ,在第13章的最后,我们想要创建一个保持活跃的过程, 这个例子喜欢:
on_exit(Pid, Fun) ->
spawn(fun() ->
Ref = monitor(process, Pid),
receive
{'DOWN', Ref, process, Pid, Info} ->
Fun(Info)
end
end).
keep_alive(Name, Fun) ->
register(Name, Pid = spawn(Fun)),
on_exit(Pid, fun(_Why) -> keep_alive(Name, Fun) end).
但是当register/2
和on_exit/2
之间的进程可能退出时,监视器将失败,我更改了keep_alive/2
,如下所示:
keep_alive(Name, Fun) ->
{Pid, Ref} = spawn_monitor(Fun),
register(Name, Pid),
receive
{'DOWN', Ref, process, Pid, _Info} ->
keep_alive(Name, Fun)
end.
在spawn_monitor/2
和register/2
之间还有一个错误,该过程可能会退出。怎么能成功运行?感谢。
答案 0 :(得分:4)
我不确定您是否有需要解决的问题。即使您的进程在register / 2之后退出,Monitor / 2也会成功。 Monitor / 2将发送“DOWN”'消息,其Info组件将是noproc。根据文件:
A' DOWN'如果Item死亡,如果Item不存在,或者如果连接丢失到Item所在的节点,则将消息发送到监视进程。 (见http://www.erlang.org/doc/man/erlang.html#monitor-2)。
所以,在原始代码中
我认为一切都很好。
答案 1 :(得分:2)
那么为什么你不想使用erlang主管行为呢?它提供了用于创建和重新启动保持活动过程的有用功能。
请参见示例:http://www.erlang.org/doc/design_principles/sup_princ.html
答案 2 :(得分:0)
在第二个示例中,如果流程在注册register
之前退出,则badarg
将失败。解决问题的最简单方法是使用try ... catch
进行注册并处理catch中的错误。
您甚至可以将catch留空,因为即使注册失败,也会发送'DOWN'
消息。
另一方面,我不会在生产系统中这样做。如果您的工作人员失败如此之快,很可能是问题在于其初始化代码,我想知道,它无法注册并停止系统。否则,它可能会失败并在无限循环中重生。