使用setjmp的时候,同一个信号只能触发一次

Linux的异常处理
    基于setjmplongjmp的运行控制方式是Linux平台上C语言处理异常的标准方案,已被广泛运用到由C语言开发的软件系统和链接库中,例如jpg解析库,加密解密库等等。setjmplongjmp是以C语言标准库函数的形式提供的,
setjmp 函数能够保存程序当前的执行环境,即程序的状态,该被保存的程序状态可以在随后程序执行的某一点被longjmp函数恢复,程序的控制流也将跳转到调用setjmp时的执行点,实现非本地局部跳转("non-local goto")的机制。
问题描述:
    在编写基于异常的代码混淆程序时,signal注册的异常信号处理程序只能执行一次,第二次发生异常时异常处理函数没有被调用。
分析:
1. 搞清楚Linux的信号处理流程:
  [1] 收到信号,例如SIGFPE
  [2] 进入signal注册的信号处理函数,此时,SIGFPE自动被加入到进程信号屏蔽字
  [3] 执行信号处理函数
  [4] 信号处理结束,恢复信号屏蔽字,SIGFPE被取消阻塞
  [5] 返回到产生信号地方继续执行
2. 分析异常处理函数没有被调用的原因:
    异常信号处理函数在结束前没有取消对SIGFPE信号的阻塞,直接调用longjmp()进行控制流转移。所以在后面的执行过程中再次遇到SIGFPE信号,系统会自动根据 信号屏蔽字进行屏蔽,异常处理函数也就无法被调用。
3. 该问题的解决办法:
    使用sigsetjmp和siglongjmp函数替换setjmp和longjmp函数。siglongjmp功能与longjmp类似,不同的是siglongjmp会自动恢复进程的信号屏蔽字,因此相同的异常信号再次发生时就不会被系统屏蔽了。


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

jmp_buf jmpbuffer;

void fun(int i){
    siglongjmp(jmpbuffer, 1);
    return;
}
int main(int argc, char** argv) {
    signal(SIGUSR2, fun );
    if( sigsetjmp(jmpbuffer, SIGUSR1) == 1){
        printf("==000====\n");
    }
/*
    struct sigaction act, oact;
    act.sa_handler=fun;
    sigemptyset(&act. sa_mask);
    act. sa_flags = 0;
    sigaction(SIGUSR2, &act, &oact);
*/
    sleep(5000);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sjx1989/article/details/49493869