【问题标题】:Erlang process termination: Where/When does it happen?Erlang 进程终止:它在哪里/何时发生?
【发布时间】:2015-02-08 21:16:54
【问题描述】:

考虑所有链接在树中的进程,可以是正式的监督树,也可以是一些临时结构。

现在,考虑一下这棵树下的某个孩子或工人,其上方是父母或主管。我有两个问题。

  1. 如果需要终止或关闭此过程,我们希望“优雅地”退出此过程,因为它可能正在更新某些帐户余额。假设我们已经正确地编写了一些终止函数,并通过适当的管道将此进程连接到其他进程。现在假设这个过程在它的主循环中工作。终止的信号进来了。这个终止发生在哪里(或者问题应该是何时)?换句话说,何时会调用终止?这个东西会在它正在运行的循环中间抢占自己并调用终止吗?它会等到循环结束但再次开始循环之前吗?它只会在接收模式下这样做吗?等等。

  2. 同样的问题,但没有编写终止函数。假设父进程是主管,并且该子进程遵循正常的 OTP 约定。父母告诉孩子关机,或者父母崩溃或其他什么。孩子处于其主循环中。何时/何地/如何发生关机?在主循环的中间?之后呢?等等。

【问题讨论】:

    标签: erlang shutdown erlang-otp erlang-supervisor


    【解决方案1】:

    in the docs (sections 12.4, 12.5, 12.6, 12.7) 解释得很好。

    有两种情况:

    1. 您的进程因一些错误的逻辑而终止。

    它会引发错误,因此它可能正在工作中,这可能很糟糕。如果你想防止这种情况,你可以尝试定义机制,它涉及两个过程。第一个开始事务,第二个执行实际工作,然后,第一个提交更改。如果第二个进程发生了不好的事情(由于错误而死),第一个进程根本不会提交更改。

    1. 您正试图从外部终止该进程。例如,当您的主管重新启动或链接的进程终止时。

    在这种情况下,您也可能处于某些事情的中间,但是 Erlang 为您提供了 trap_exit 标志。这意味着,该进程不会死亡,而是会收到一条您可以处理的消息。这反过来意味着,terminate 函数将在您到达 receive 块后被调用。因此,该进程将完成一大块工作,当它准备好进行下一个工作时,它将调用terminate,然后就死掉了。

    因此您可以使用trap_exit 绕过退出。您也可以绕过trap_exit发送exit(Pid, kill),即使它捕获退出也会终止进程。

    没有办法绕过exit(Pid, kill),所以要小心使用。

    【讨论】:

    • 我认为文档中的解释不是“很好”,而且相当复杂并且分布在不同的章节中,这就是我不得不问这个问题的原因。不过你的回答很好,所以我接受。
    • 如果你不使用trap退出,进程会在当前的植入中,当你用完reductions或者以某种方式被挂起时退出。这是当前实现的工作方式,不是保证。很少保证何时传递异步信号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 2021-09-05
    • 2011-01-13
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多