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



我目前正在阅读编程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之间,进程可能会退出。这怎么会成功运行?谢谢

我不确定您是否有需要解决的问题。即使您的进程在注册/2之后退出,监视器/2也会成功。监视器/2将发送一条"向下"消息,其信息组件将为noproc。根据文件:

如果Item死亡,如果Item不存在,或者如果与Item所在节点的连接丢失,将向监控进程发送"DOWN"消息。(请参阅http://www.erlang.org/doc/man/erlang.html#monitor-2) 。

所以,在你的原始代码

  1. 注册关联方Pid的名称
  2. Pid死亡
  3. 调用on_exit并执行monitor/2
  4. 监视器立即发送一条"DOWN"消息,该消息由on_exit派生的函数接收
  5. 接收到的语句的Fun(Info)调用keep_alive/2执行

我觉得一切都很好。

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

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

在第二个示例中,如果进程在注册之前退出,register将以badarg失败。最简单的方法是用try ... catch包围寄存器并处理catch中的错误。

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

另一方面,在生产系统中我不会这么做。如果你的工作人员失败得如此之快,很可能问题出在它的初始化代码中,我想知道,它未能注册并停止了系统。否则,它可能会失败,并在一个无休止的循环中重生。

最新更新