调试Erlang心脏超时

时间:2011-04-13 12:58:54

标签: erlang heartbeat

我使用heart程序在Erlang节点无响应时重新启动它。但是,我发现很难理解为什么节点冻结。 SASL日志不显示任何错误,我自己的日志似乎没有显示在那些时候发生的任何重大事件。有人可以提供调试这类事情的建议吗?

3 个答案:

答案 0 :(得分:2)

默认情况下,心脏程序发出SIGKILL以消除无响应的VM,以便快速启动新VM。这使得获取有关VM的任何有用信息几乎不可能。我过去尝试过的东西是修补心脏程序以避免硬杀,而是让VM创建崩溃转储和coredump。我使用了这样的补丁(这个是针对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秒钟。如果您没有获得完整的故障转储,则可能需要增加此休眠时间。然后,心脏然后尝试两次发出SIGQUIT,希望获得一个coredump,如果失败,则发出SIGKILL

请注意,由于等待崩溃转储和coredump所需的时间,此修补程序将减慢心脏的VM重启速度。如果您在生产中使用它,请注意此限制。

答案 1 :(得分:1)

如果你知道它冻结的原因,你可以尝试使用dbg跟踪模块。

http://www.erlang.org/doc/man/dbg.html

简而言之,尝试

dbg:tracer(), dbg:p(all,c), dbg:tpl(Module, Function, x).

如果您想停止此跟踪问题

dbg:ctpl()

有关详细信息,请参阅文档。

注意:将模块和函数更改为您要跟踪的任何内容,保留x原样。您也可以跳过Function并仅提供Module,x。

警告:在实时系统上运行此操作可能很危险,因为要打印到shell的信息量可能非常大。

答案 2 :(得分:1)

您可以尝试从erlang:halt/1调用HEART_COMMAND,从而从无响应的节点创建崩溃转储。

您可以尝试使用erl_call工具,例如-a erlang halt 123

如果erlang节点无法响应,这也是有趣的信息。

您是否尝试过增加`HEART_BEAT_TIMEOUT?也许节点只是陷入了一点,但是没有超时,但是没有冻结。