Что-то не так с sigsetjmp - PullRequest
       0

Что-то не так с sigsetjmp

0 голосов
/ 30 декабря 2011

Я читаю APUE, Глава 10. Вот мой код.

#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;
}

Я думал, что результат будет таким:

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

, но кажется, что-то не так,На самом деле это мой вывод:

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

, то есть никаких сигналов.Пожалуйста, помогите мне.

1 Ответ

1 голос
/ 30 декабря 2011

Я думаю, проблема, вероятно, в том, что вы используете signal(), а не sigaction() для настройки обработки сигнала.И signal() не маскирует никакие другие сигналы - поэтому нет сигналов, которые можно было бы показать как заблокированные.Я изменил ваш код, как показано ниже, чтобы использовать signal() и sigaction() в зависимости от того, есть ли какие-либо аргументы или нет.

#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 с текущим XCode (4.2?)Я получаю (например):

$ ./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: 
$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...