c - 如何通过信号重复重启程序

标签 c linux signals posix

我想要一种方便的方法来重新启动程序。我以为我可以捕获一个信号(示例中为 USR1)并调用 exec。

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

char* const* args;
void restart() {
    printf("restarting\n");
    execv(args[0], args);
}

int main(int argc, char* const argv[]) {
    printf("Starting\n");
    args = argv;
    signal(SIGUSR1, restart);
    raise(SIGUSR1); // could use pkill -SIGUSR1 file-name instead
    pause();
    printf("Terminated normally\n");
    return 0;
}

上面的例子还可以。输出为

Starting
restarting
Starting

然后它挂起。其他信号仍然可以接收。

我认为我只是未能清除信号。预期的行为是程序无限期地重新启动。

最佳答案

Linux 的 man 2 signal 解释了当您使用 signal 设置信号处理程序时会发生什么。有两种可能:

  1. 信号的处理重置为SIG_DFL,然后调用处理程序。要再次处理该信号,需要重新建立信号处理程序。这会如您所料发挥作用。

或者:

  • 信号被阻塞,然后处理程序被调用。当处理程序返回时,信号将被解除阻塞。如果处理程序没有返回,信号仍然被阻止,这就是您所发生的情况。
  • 因此,一个可以使用您的代码,而另一个则不能。但这两者适用哪一个呢?没有可靠的方法可以知道。 Posix 允许这两种可能性,并且这两种可能性存在于不同的平台上。因此,Linux 联机帮助页建议:

    The only portable use of signal() is to set a signal's disposition to SIG_DFL or SIG_IGN... [D]o not use it for [the purpose of establishing a signal handler].

    POSIX.1 solved the portability mess by specifying sigaction(2), whichprovides explicit control of the semantics when a signal handler is invoked; use that interface instead of signal().

    这是个好建议。当您更改为使用 sigaction 时,您可能会想要选择上面的第一个选项,该选项需要:

    sa.sa_flags = SA_RESETHAND | SA_NODEFER
    

    这也来自 Linux 手册页,非常值得完整阅读。 (当然,sigaction 联机帮助页更加相关。)

    关于c - 如何通过信号重复重启程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60691017/

    相关文章:

    c - linux c 编程中的信号

    audio - 向我解释 FFT

    python - 如何覆盖键盘中断? (Python)

    c - ListEntry 类的使用

    Java 匈牙利数字格式和 Linux 文件系统

    linux - 将 Github repo 推送到其他现有帐户(而不是默认帐户)?

    linux - BASH - 传递给 sFTP 的带空格的文件名无法正确解析

    当 int arr = 1 && arr; 时代码崩溃但不是 int arr = 0 && arr;

    c - 为什么用太长的初始化器初始化的字符串会像这样

    c - C 中的二维初始化语法