【问题标题】:sigaction's signal handler not called in child processsigaction 的信号处理程序未在子进程中调用
【发布时间】:2016-03-13 22:09:35
【问题描述】:

我有一个程序,它为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 的设置方式正确,但复活的应用程序只是默默地崩溃了。

我错过了什么?

【问题讨论】:

    标签: c linux signals sigaction


    【解决方案1】:

    您缺少的是,默认情况下,当您处理一个信号时,该信号的任何额外传递都会被阻止,直到处理函数返回。由于您永远不会从信号处理程序返回(您改为调用execl()),因此您的第二个SIGSEGV 不会被传递。它一直在等待您的信号处理函数返回,而它永远不会返回。

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

    act.sa_flags = SA_NODEFER;
    

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

    其他几个辅助点:

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

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

    【讨论】:

    • 请注意,execl() 规范说挂起的信号由子进程继承。也有关于将信号处理程序重置为默认值的规则。这是一个密集阅读 - 页面中有很多信息。
    • @JonathanLeffler 我对forks 手册感到困惑,您可以在哪里找到:The child's set of pending signals is initially empty
    • @MichałWalenciak :它最初必须是空的,真的,因为它是一个全新的过程,还没有人向它发送任何信号。
    • @MichałWalenciak:在fork() 之后,这是真的;但是您的代码中没有fork();您只是使用execl() 来运行新的可执行文件,并且(令我惊讶的是)我没有看到任何说当您执行新程序(或当前程序的新副本)时挂起信号被丢弃。我可能错过了相关信息。
    • @JonathanLeffler:我有叉子;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    相关资源
    最近更新 更多