7

我有一个gen_server运行,它必须在正常停止或意外崩溃时清理其状态。清理基本上包括删除一些文件。

此时,当gen_server崩溃或正常停止时,清理完成terminate/2

如果崩溃,有什么理由terminate/2不会被调用?gen_server

如果意外死亡,是否应该有任何其他进程监视gen_server等待进行清理的过程?gen_server

所以,代码是这样的:

terminate(normal, State) ->
    % Invoked when the process stops
    % Clean up the mess
terminate(Error, State) ->
    % Invoked when the process crashes
    % Clean up the mess

编辑:我在官方邮件列表中发现了这封电子邮件,它谈论的是同一件事:

http://groups.google.com/group/erlang-programming/browse_thread/thread/9a1ba2d974775ce8

正如亚当在下面所说,如果我们想避免将存在困在 中gen_server,我们可以使用不同的方法。

但是如果我们捕获存在,terminate/2似乎是一个安全的地方进行清理,因为它总是会被调用。此外,我们必须正确处理何时'EXIT'发送到terminate/2handle_call/3尝试在工人和主管之间正确传播错误。

4

2 回答 2

11

terminate/2在内部发生崩溃时调用,gen_server即使它没有陷阱退出,如果它从链接到它的其他进程接收到“退出”,它也不会被调用,如果你需要清理,那么它应该陷阱退出(使用process_flag(trap_exit, true))。

这种行为有点不幸,因为它很难为进程编写可靠的关闭gen_server过程。此外,为了能够运行而捕获出口也不是一个好习惯terminate/2,因为您可能会捕获许多其他错误,从而使调试系统变得更加困难。

我会考虑三个选项:

  1. 在流程的下一个实例启动时处理剩余的文件(例如,在 中init/1
  2. 陷阱退出,清理文件,然后再次以同样的原因崩溃
  3. gen_server有一个监控其唯一目的是清理文件的第三个进程

选项 1 可能是最好的选择,因为至少代码不会捕获退出并且您可以免费获得持久状态。由于上述原因,选项 2 不太好,它可以隐藏和掩盖其他错误。3 是混乱的,因为在重新启动之前可能无法完成清理过程gen_server

仔细考虑为什么要清理,以及当进程崩溃时是否真的必须这样做(毕竟这是一个错误)。小心不要最终做太多的防御性编程。

于 2011-02-25T15:49:24.723 回答
0

这是非常新鲜和相关的, 何时在 gen_server 中调用 terminate/2?

于 2016-06-24T01:39:29.207 回答