我有一个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/2
和handle_call/3
时正确处理,并尝试在工人和主管之间正确传播错误。
答案 0 :(得分:11)
terminate/2
内发生崩溃时会调用 gen_server
,即使它没有捕获退出,如果它从链接到它的某个其他进程收到'EXIT',它也不会被调用,如果你需要清理它,它应该捕获退出(使用process_flag(trap_exit, true)
)。
这种行为有点不幸,因为它很难为gen_server
进程编写可靠的关闭过程。此外,仅仅为了能够运行terminate/2
来捕获出口并不是一个好习惯,因为您可能会捕获许多其他错误,这使得调试系统变得更加困难。
我会考虑三种选择:
init/1
中)gen_server
,其唯一目的是清理文件选项1可能是最好的选择,因为至少代码不会捕获退出并且您可以免费获得持久状态。由于上述原因,选项2不太好,它可以隐藏和掩盖其他错误。 3是混乱的,因为在gen_server
再次启动之前可能无法完成清理过程。
仔细考虑你要清理的原因,以及在进程崩溃时是否真的必须完成(毕竟这是一个bug)。要小心,你最终不要做太多的防御性编程。
答案 1 :(得分:0)