什么时候在看门狗线程中引起段错误比正常退出以停止进程更可取?

When is it preferable to cause a segfault in a watchdog thread versus exiting normally to stop a process?

我想知道是否有 曾经 一个很好的理由以描述的方式退出看门狗线程,而不是以 exit() 退出。在我遇到的让我想起这个问题的代码中,段错误是由使用奇怪的行 *(char **)0 = "watchdog timeout";.

取消引用空指针引起的

除非我弄错了,一个调用exit()的线程会终止整个进程。我将段错误解释为错误,而不是预期的行为,但也许有时需要它。

void *watchdog_loop(void *arg) {
    time_t now;
    while(foo) {
        sleep(1);
        now = current_time();
        if (watchdog_timeout && now - bar > watchdog_timeout) {
            raise(SIGSEGV); //something went wrong
        }
    }
    return NULL;
}

Is there ever a time that it would be more desirable to have a watchdog loop segfault intentionally, versus exiting nonzero?

引出未定义的行为是不可取的,示例代码正是这样做的。特别要注意的是,尽管在某些系统上它可能可靠地这样做,但不需要该代码来导致将段错误传递给进程。

然而,人们可能确实更喜欢通过信号而不是调用 exit() 来终止进程,以便在不执行任何应用程序或库清理代码的情况下实现终止。对于看门狗来说,这是一个合理的目标。然而,即使在那种情况下,

  1. raise()abort() 函数会明确地 导致将信号传递给进程。

  2. SIGSEGV 似乎是一个奇怪的信号选择。 SIGABRTSIGTERMSIGKILL 中的任何一个对我来说都更有意义。其中,

    • SIGKILL 不是由 C 语言规范指定的,而是由 POSIX (也许还有其他人)指定的。在 POSIX 系统上,SIGKILL 无法被阻塞或捕获,因此它是一个非常好的候选信号,可以尽可能快速和可靠地终止进程。

    • SIGABRTabort() 函数使用,它也费尽心思试图克服程序对以这种方式终止的阻力。这是用于触发故意异常程序终止的最自然的标准函数。

    • SIGTERM 可以被捕获和/或阻塞,但与 SIGKILL 不同的是,它是由 C 语言规范定义的,因此更具可移植性。但我真的看不出比 SIGABRT 有任何优势,除非你 打算 允许它被处理。

  3. 另一种选择是 _exit()(POSIX)或 _Exit()(C99 或更高版本)。这些执行的关闭比您预期的通过信号终止更干净,但不执行大多数清理代码。打开的文件将被关闭,父进程将观察到进程以失败状态正常终止,而不是被信号杀死。