Можно ли использовать как собственный обработчик сигнала sigaction, так и pthread_sigmask? - PullRequest
1 голос
/ 26 августа 2011

Я реализую простой таймер, который выдает сигнал RT по истечении срока действия. Я хочу зарегистрировать обработчик сигнала (используя sigaction), который вызывается при появлении сигнала. Тем временем основной код ожидает вызова сигнала с использованием sigwaitinfo.

Реализация либо обработчика сигнала, либо sigwaitinfo работает исключительно хорошо. Однако, когда используются оба, обработчик сигнала никогда не вызывается. Я пытался переключить порядок; т.е. регистрация обработчика перед блокировкой сигнала. Не имеет никакого значения

Вот код

// gcc -Wall -o sigwait_example sigwait_example.c -lrt
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <string.h>

#define install_handler(sig,sa) if( sigaction(sig, &sa, NULL) == -1 ){ \
                                    perror("sigaction"); }
#define SIG SIGRTMIN+1

volatile int flag=0;

void handler(int signum){
    flag++;
}

int main(void){
    struct itimerspec its;
    sigset_t blocked;
    siginfo_t si;
    timer_t timerid;
    struct sigevent evt;
    struct sigaction sa;

    evt.sigev_notify = SIGEV_SIGNAL;
    evt.sigev_signo = SIG;
    evt.sigev_value.sival_ptr = &timerid;
    if ( timer_create(CLOCK_REALTIME, &evt, &timerid) ){
        perror("timer_create");
    }

    //setup timer
    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = 0.1*1E9;
    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = 0;

    //arm the timer 
    if ( timer_settime(timerid, 0, &its, NULL) )
        perror("timer_settime");

    sigemptyset(&blocked);
    sigaddset(&blocked, SIG);
    //add SIG to blocked signals
    pthread_sigmask(SIG_BLOCK, &blocked, NULL);

    sa.sa_flags = SA_SIGINFO; //use this flag to set custom handler
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    install_handler(SIG,sa);

    while ( sigwaitinfo(&blocked, &si) == -1 && errno == EINTR );
    printf("received signal: %s, flag=%d\n",strsignal(si.si_signo),flag);       
    //while(flag==0) sleep(1); //use this when only signal handler is used

    timer_delete(timerid);

    return 0;
}

Я делаю это в основном для образовательных целей, так как мне нужно узнать как можно больше о том, как потоки отправляются / блокируются, так как я буду использовать их в потоках.

1 Ответ

1 голос
/ 26 августа 2011

Это невозможно, поскольку sigwaitinfo() удаляет сигнал из очереди.

Однако вы можете использовать sigaction(SIG, NULL, &sa) для получения структуры sigaction этого сигнала и выполнения обработчика.

...