在Linux中使用longjmp有一个问题,当捕捉到一个信号的时候进入信号处理函数,此时当前信号自动加入到
进程的信号屏蔽字中,这就阻止了后来的这种信号中断该信号处理程序。如果用longjmp跳出信号处理程序,那么该进程的信号屏蔽字不会被恢复到调用信号处理程序前的信号屏蔽字。
如果想恢复的话,就要使用sigsetjmp和siglongjmp函数。
详细说明见APUE2 P266
下面程序展示了两者的区别:
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <unistd.h> #include <errno.h>
extern errno; //static sigjmp_buf jmpbuf; static jmp_buf jmpbuf1; static void sig_usr1(int signo); static void pr_mask(char* ptr);
int main(int argc, char** argv) { sigset_t set; struct sigaction act, oact;
sigemptyset(&set); sigaddset(&set, SIGINT); if(sigprocmask(SIG_SETMASK, &set, NULL) < 0){ perror("sigparocmask error"); exit(1); }
act.sa_flags = 0; sigemptyset(&act.sa_mask); act.sa_handler = sig_usr1; if(sigaction(SIGUSR1, &act, &oact) < 0){ perror("sigaction error"); exit(2); }
pr_mask("before main: "); /*** if(sigsetjmp(jmpbuf, 1)){ pr_mask("end main: "); } ***/ if(setjmp(jmpbuf1)){ pr_mask("end main: "); }
while(1){ pause(); } exit(0); }
static void sig_usr1(int signo) { pr_mask("int sig_int: "); // siglongjmp(jmpbuf, 1); longjmp(jmpbuf1, 1); }
static void pr_mask(char* ptr) { sigset_t sigset; int errno_save; int ret;
errno_save = errno; ret = sigprocmask(0, NULL, &sigset); if(ret == -1){ perror("sigprocmask error"); exit(1); }
printf("%s", ptr);
if(sigismember(&sigset, SIGINT)){ printf("SIGINT "); } if(sigismember(&sigset, SIGQUIT)){ printf("SIGQUIT "); } if(sigismember(&sigset, SIGUSR1)){ printf("SIGUSR1 "); } if(sigismember(&sigset, SIGALRM)){ printf("SIGALRM "); }
printf("\n"); errno = errno_save; }
|
阅读(1430) | 评论(0) | 转发(0) |