【发布时间】:2011-04-18 00:15:21
【问题描述】:
我使用heart 程序在 Erlang 节点无响应时重新启动它。但是,我发现很难理解 为什么 节点会冻结。 SASL 日志没有显示任何错误,而我自己的日志似乎也没有显示当时发生的任何异常情况。任何人都可以提供有关调试此类事情的建议吗?
【问题讨论】:
我使用heart 程序在 Erlang 节点无响应时重新启动它。但是,我发现很难理解 为什么 节点会冻结。 SASL 日志没有显示任何错误,而我自己的日志似乎也没有显示当时发生的任何异常情况。任何人都可以提供有关调试此类事情的建议吗?
【问题讨论】:
默认情况下,heart 程序会发出一个SIGKILL 来杀死无响应的虚拟机,以便它可以快速启动一个新虚拟机。这使得几乎不可能获得有关 VM 的任何有用信息。我过去尝试过修补心脏程序以避免硬杀,而是让虚拟机创建故障转储和核心转储。我使用了这样的补丁(这个是针对 Erlang/OTP R14B02 的):
--- erts/etc/common/heart.c.orig 2011-04-17 12:11:24.000000000 -0400
+++ erts/etc/common/heart.c 2011-04-17 12:12:36.000000000 -0400
@@ -559,10 +559,11 @@
int res;
if(heart_beat_kill_pid != 0){
pid = (pid_t) heart_beat_kill_pid;
- res = kill(pid,SIGKILL);
+ res = kill(pid,SIGUSR1);
+ sleep(4);
for(i=0; i < 5 && res == 0; ++i){
sleep(1);
- res = kill(pid,SIGKILL);
+ res = kill(pid,i < 2 ? SIGQUIT : SIGKILL);
}
if(errno != ESRCH){
print_error("Unable to kill old process, "
如您所见,使用此补丁后,heart 将首先发出SIGUSR1 以尝试让 VM 创建故障转储。由于这可能需要一段时间,因此心脏会休眠 4 秒。如果您没有获得完整的故障转储,您可能必须增加此睡眠时间。之后,heart 尝试两次发出SIGQUIT 以希望获得核心转储,如果失败,则发出SIGKILL。
请注意,由于等待故障转储和核心转储所需的时间,此补丁会减慢 heart 的 VM 重启速度。如果您在生产中使用它,请注意此限制。
【讨论】:
您可以尝试从您的HEART_COMMAND 调用erlang:halt/1,从而从无响应的节点创建故障转储。
您可以尝试使用erl_call 工具,例如-a erlang halt 123.
如果 erlang 节点无法响应这也是有趣的信息。
您是否尝试增加 `HEART_BEAT_TIMEOUT?也许节点只是有点卡住了,错过了超时但没有冻结。
【讨论】:
如果您知道它冻结的原因,您可以尝试使用 dbg 跟踪模块。
http://www.erlang.org/doc/man/dbg.html
总之试试
dbg:tracer(), dbg:p(all,c), dbg:tpl(Module, Function, x).
如果您想停止此跟踪问题
dbg:ctpl()
有关详细信息,请参阅文档。
注意:将 Module 和 Function 更改为您想要跟踪的任何内容,保持 x 不变。你也可以跳过Function,只给出Module, x。
警告:在实时系统上运行此程序可能很危险,因为要打印到 shell 的信息量可能非常巨大。
【讨论】:
dbg 跟踪到文件。让它运行一段时间可能会起作用,并且只有在检测到故障情况后才检查跟踪。