Chinaunix首页 | 论坛 | 博客
  • 博客访问: 433880
  • 博文数量: 103
  • 博客积分: 5010
  • 博客等级: 大校
  • 技术积分: 971
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-11 17:22
文章分类
文章存档

2008年(77)

2007年(26)

我的朋友

分类: LINUX

2007-12-30 01:11:33

在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) |
给主人留下些什么吧!~~