3

当 Erlang 节点无响应时,我使用heart程序重新启动它。但是,我发现很难理解节点冻结的原因。SASL 日志没有显示任何错误,而我自己的日志似乎也没有显示当时发生的任何异常情况。任何人都可以就调试这类事情提供建议吗?

4

3 回答 3

2

默认情况下,heart 程序发出 aSIGKILL来杀死无响应的 VM,以便它可以快速启动一个新 VM。这使得几乎不可能获得有关 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, "

正如你所看到的,有了这个补丁,心脏会首先发出一个SIGUSR1尝试让虚拟机创建一个故障转储。由于这可能需要一段时间,因此心脏会休眠 4 秒。如果您没有获得完整的故障转储,您可能必须增加此睡眠时间。之后,heart 然后尝试两次发出 aSIGQUIT以希望获得一个 coredump,如果失败,则发出 a SIGKILL

请注意,由于等待故障转储和核心转储所需的时间,此补丁将减慢 heart 的 VM 重启速度。如果您在生产中使用它,请注意此限制。

于 2011-04-17T16:15:21.230 回答
1

如果您知道它为什么会冻结,您可以尝试使用 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 的信息量可能非常巨大。

于 2011-04-13T14:10:10.093 回答
1

您可以尝试erlang:halt/1从您的呼叫中调用,HEART_COMMAND从而从无响应的节点创建故障转储。

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

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

您是否尝试增加“HEART_BEAT_TIMEOUT”?也许节点只是有点卡住了,错过了超时但没有冻结。

于 2011-04-14T18:52:52.230 回答