简体   繁体   English

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

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

I've a program, which installs a signal handler for SIGSEGV . 我有一个程序,它为SIGSEGV安装一个信号处理程序。 In signal handler ( I try to catch crash ) I restart my application. 在信号处理程序(我试图抓住崩溃)我重新启动我的应用程序。

But when my application is resurrected it doesn't handle SIGSEGV anymore. 但是当我的应用程序复活时,它不再处理SIGSEGV

Here's an example: 这是一个例子:

#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;
}

what I get in output is: 我得到的输出是:

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

So I can see sighandler was set in right way, but resurrected app simply crashed silently. 所以我可以看到sighandler以正确的方式设置,但复活的应用程序只是默默地崩溃。

What am I missing? 我错过了什么?

What you're missing is that, by default, when you handle a signal, any additional delivery of that signal is blocked until the handling function returns. 您缺少的是,默认情况下,当您处理信号时,该信号的任何其他传送都将被阻止,直到处理函数返回为止。 Since you never return from your signal handler (you call execl() instead) then your second SIGSEGV isn't being delivered. 因为你永远不会从你的信号处理程序返回(你调用execl() )然后你的第二个SIGSEGV没有交付。 It's waiting until your signal handler function returns, which it never will. 它等待你的信号处理函数返回,它永远不会。

To get the results you seem to want, you have to change this default behavior. 要获得您想要的结果,您必须更改此默认行为。 The easiest way to do that is to set the appropriate flag when you register the signal handler: 最简单的方法是在注册信号处理程序时设置适当的标志:

act.sa_flags = SA_NODEFER;

and you'll get the recursive behavior you seem to be looking for. 你会得到你似乎在寻找的递归行为。 Your other option is to unblock it with sigprocmask() before your execl() call. 您的另一个选择是在execl()调用之前使用sigprocmask()取消阻止它。

Couple of other ancillary points: 几个其他辅助点:

  1. puts() , printf() , execl() and exit() are not async-safe, and shouldn't be called from a signal handler. puts()printf()execl()exit()不是异步安全的,不应该从信号处理程序中调用。 execle() and _exit() would be OK. execle()_exit()就可以了。

  2. You're not calling execl() properly. 你没有正确地调用execl() The first argument should be the application name, so execl(app, app, (char *)0); 第一个参数应该是应用程序名称,所以execl(app, app, (char *)0); would be correct. 会是对的。 The cast to char * , which you omit, is required. 您省略的转换为char *是必需的。

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

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