如何在Erlang中创建一个保持活动的进程

时间:2014-09-02 07:12:52

标签: erlang

我正在阅读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/2on_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/2register/2之间还有一个错误,该过程可能会退出。怎么能成功运行?感谢。

3 个答案:

答案 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. register将名称与Pid相关联
  2. Pid死了
  3. on_exit被调用并且monitor / 2被执行
  4. 监视器立即发送“DOWN”'由on_exit
  5. 生成的函数接收的消息
  6. 收到的声明的Fun(Info)执行调用keep_alive / 2
  7. 我认为一切都很好。

答案 1 :(得分:2)

那么为什么你不想使用erlang主管行为呢?它提供了用于创建和重新启动保持活动过程的有用功能。

请参见示例:http://www.erlang.org/doc/design_principles/sup_princ.html

答案 2 :(得分:0)

在第二个示例中,如果流程在注册register之前退出,则badarg将失败。解决问题的最简单方法是使用try ... catch进行注册并处理catch中的错误。

您甚至可以将catch留空,因为即使注册失败,也会发送'DOWN'消息。

另一方面,我不会在生产系统中这样做。如果您的工作人员失败如此之快,很可能是问题在于其初始化代码,我想知道,它无法注册并停止系统。否则,它可能会失败并在无限循环中重生。