有些错此时sigsetjmp [英] Some wrong about sigsetjmp

查看:132
本文介绍了有些错此时sigsetjmp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读了APUE,第10章。这是我的code。

I am reading the APUE, Chapter 10. Here is my code.

#include "apue.h"
#include <unistd.h>
#include <setjmp.h>
#include <time.h>
#include <errno.h>

static void sig_usr1(int), sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjmp;

int 
main(void)
{
    if(signal(SIGUSR1, sig_usr1) == SIG_ERR)
        err_sys("signal(SIGUSR1) error");
    if(signal(SIGALRM, sig_alrm) == SIG_ERR)
        err_sys("signal(SIGALRM) error");
    //print signal.
    pr_mask("Starting main: ");
    if(sigsetjmp(jmpbuf, 1)) {
        pr_mask("End main: ");
        exit(0);
    }
    canjmp = 1;
    for(;;)
        pause();
}

static void
sig_usr1(int signo)
{
    time_t starttime;

    if(canjmp == 0) {
        return;
    }

    pr_mask("starting sig_usr1: ");
    alarm(3);
    starttime = time(NULL);
    for(;;) 
        if(time(NULL) > starttime + 5)
            break;
    pr_mask("finishing sig_usr1: ");
    canjmp = 0;
    siglongjmp(jmpbuf, 1);
}

static void
sig_alrm(int signo)
{
    pr_mask("in sig_arlm: ");
}

void
pr_mask(const char *str)
{
    sigset_t    sigset;
    int         errno_save;

    errno_save = errno;     /* we can be called by signal handlers */
    if (sigprocmask(0, NULL, &sigset) < 0)
        err_sys("sigprocmask error");

    printf("%s", str);
    if (sigismember(&sigset, SIGUSR1))  printf("SIGUSR1 ");
    if (sigismember(&sigset, SIGALRM))  printf("SIGALRM ");
    /* remaining signals can go here  */

    printf("\n");
    errno = errno_save;
}

我想输出会是这样的:

I thought the output would be like this:

Starting main:
starting sig_usr1: SIGUSR1
in sig_alrm: SIGUSR1 SIGALRM
finishing sig_usr1: SIGUSR1
End main:

但似乎有些不对劲,这是我实际上输出的:

but it seems something wrong, this is my output in fact:

Starting main:
starting sig_usr1: 
in sig_alrm: 
finishing sig_usr1: 
End main:

这是没有信号。请帮我。

that is no signals. Please help me.

推荐答案

我觉得麻烦的是可能是你正在使用信号(),而不是的sigaction()设置的信号处理。和信号()不掩盖任何其他信号 - 所以有没有信号显示为被封锁。我修改了code,如下图所示,使用信号()的sigaction()根据是否有任何争论或没有。

I think the trouble is probably that you are using signal() and not sigaction() to set the signal handling. And signal() does not mask any other signals - so there are no signals to show as being blocked. I modified your code as shown below, to use signal() and sigaction() depending on whether there are any arguments or not.

#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

typedef void (*Handler)(int);
static void sig_usr1(int), sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjmp;
static void pr_mask(const char *str);

static void err_sys(const char *str)
{
    int errnum = errno;
    fprintf(stderr, "%s (%d: %s)\n", str, errnum, strerror(errnum));
    exit(1);
}

static void set_sigaction(int signum, Handler handler)
{
    struct sigaction nact;
    nact.sa_handler = handler;
    sigfillset(&nact.sa_mask);
    //sigemptyset(&nact.sa_mask);
    nact.sa_flags = 0;
    if (sigaction(signum, &nact, 0) != 0)
        err_sys("Failed to set signal handling");
}

int 
main(int argc, char **argv)
{
    printf("PID = %u\n", (unsigned)getpid());
    if (argc > 1)
    {
        if (signal(SIGUSR1, sig_usr1) == SIG_ERR)
            err_sys("signal(SIGUSR1) error");
        if (signal(SIGALRM, sig_alrm) == SIG_ERR)
            err_sys("signal(SIGALRM) error");
    }
    else
    {
        set_sigaction(SIGUSR1, sig_usr1);
        set_sigaction(SIGALRM, sig_alrm);
    }
    //print signal.
    pr_mask("Starting main: ");
    if (sigsetjmp(jmpbuf, 1)) {
        pr_mask("End main: ");
        exit(0);
    }
    canjmp = 1;
    for (;;)
        pause();
}

static void
sig_usr1(int signo)
{
    time_t starttime;

    if (canjmp == 0) {
        return;
    }

    pr_mask("starting sig_usr1: ");
    alarm(3);
    starttime = time(NULL);
    for (;;) 
        if (time(NULL) > starttime + 5)
            break;
    pr_mask("finishing sig_usr1: ");
    canjmp = 0;
    siglongjmp(jmpbuf, 1);
}

static void
sig_alrm(int signo)
{
    pr_mask("in sig_arlm: ");
}

void
pr_mask(const char *str)
{
    sigset_t    sigset;
    int         errno_save;

    errno_save = errno;     /* we can be called by signal handlers */
    if (sigprocmask(0, NULL, &sigset) < 0)
        err_sys("sigprocmask error");

    printf("%s", str);
    if (sigismember(&sigset, SIGUSR1))  printf("SIGUSR1 ");
    if (sigismember(&sigset, SIGALRM))  printf("SIGALRM ");
    /* remaining signals can go here  */

    printf("\n");
    errno = errno_save;
}

运行于MacOS X的10.7.2与当前的X code(?4.2),我得到(例如):

Running on MacOS X 10.7.2 with current XCode (4.2?), I get (for example):

$ ./sigtest
PID = 11066
Starting main: 
starting sig_usr1: SIGUSR1 SIGALRM 
finishing sig_usr1: SIGUSR1 SIGALRM 
in sig_arlm: SIGUSR1 SIGALRM 
End main: 
$ ./sigtest 1
PID = 11067
Starting main: 
starting sig_usr1: SIGUSR1 
in sig_arlm: SIGUSR1 SIGALRM 
finishing sig_usr1: SIGUSR1 
End main: 
$

这篇关于有些错此时sigsetjmp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆