繁体   English   中英

在子进程中没有调用sigaction的信号处理程序

[英]sigaction's signal handler not called in child process

我有一个程序,它为SIGSEGV安装一个信号处理程序。 在信号处理程序(我试图抓住崩溃)我重新启动我的应用程序。

但是当我的应用程序复活时,它不再处理SIGSEGV

这是一个例子:

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

const char * app = 0;

void sig_handler(int signo)
{
    puts("sig_handler");

    const pid_t p = fork();

    if (p == 0)
    {
        printf("Running app %s\n", app);
        execl(app, 0);
    }

    exit(1);
}


int main(int argc, char** argv)
{
    app = argv[0];

    struct sigaction act;
    sigemptyset(&act.sa_mask);

    act.sa_handler = sig_handler;
    act.sa_flags = 0;

    const int status = sigaction(SIGSEGV, &act, 0) == 0;     
    printf("signaction = %d\n", status);

    sleep(5);

    int* a = 0;
    int b = *a;

    return 0;
}

我得到的输出是:

./signals 
signaction = 1
sig_handler
Running app ./signals
signaction = 1

所以我可以看到sighandler以正确的方式设置,但复活的应用程序只是默默地崩溃。

我错过了什么?

您缺少的是,默认情况下,当您处理信号时,该信号的任何其他传送都将被阻止,直到处理函数返回为止。 因为你永远不会从你的信号处理程序返回(你调用execl() )然后你的第二个SIGSEGV没有交付。 它等待你的信号处理函数返回,它永远不会。

要获得您想要的结果,您必须更改此默认行为。 最简单的方法是在注册信号处理程序时设置适当的标志:

act.sa_flags = SA_NODEFER;

你会得到你似乎在寻找的递归行为。 您的另一个选择是在execl()调用之前使用sigprocmask()取消阻止它。

几个其他辅助点:

  1. puts()printf()execl()exit()不是异步安全的,不应该从信号处理程序中调用。 execle()_exit()就可以了。

  2. 你没有正确地调用execl() 第一个参数应该是应用程序名称,所以execl(app, app, (char *)0); 会是对的。 您省略的转换为char *是必需的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM