ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

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

2019-10-27 07:51:05  阅读:225  来源: 互联网

标签:sigaction c-3 linux signals


我有一个程序,用于为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()取消阻止它.

其他几个辅助点:

> puts(),printf(),execl()和exit()不是异步安全的,因此不应从信号处理程序中调用. execle()和_exit()可以.
>您未正确调用execl().第一个参数应该是应用程序名称,因此execl(app,app,(char *)0);是正确的.您必须省略对*的强制转换.

标签:sigaction,c-3,linux,signals
来源: https://codeday.me/bug/20191027/1942917.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有