sigprocmask не восстанавливает мой обработчик сигнала

У меня проблема с моим кодом C Unix. Я скопирую важные части: поэтому после первой sigprocmask, которую я посылаю сигнал, после SIG_UNBLOCK, не работает предыдущий дескриптор (gestisciSignalDopoReg), вместо этого стандартный дескриптор управляет моим сигналом, поэтому он просто завершает процесс... Что не так? Спасибо

struct sigaction gestoreSegnale;
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask,SIGTERM);
sigaddset(&mask,SIGINT);
sigaddset(&mask,SIGALRM);
sigaddset(&mask,SIGQUIT);
sigaddset(&mask,SIGHUP);
sigaddset(&mask,SIGSEGV);
sigaddset(&mask,SIGILL);
sigaddset(&mask,SIGPIPE);
void setSegnali(int segn,__sighandler_t handler){
  gestoreSegnale.sa_handler=handler;
  gestoreSegnale.sa_mask=mask;

  sigaction(segn, &gestoreSegnale, NULL);
}
void eseguiSetSegnali(__sighandler_t handler){
  setSegnali(SIGQUIT, handler);
  setSegnali(SIGSEGV, handler);
  setSegnali(SIGILL, handler);
  setSegnali(SIGHUP, handler);
  setSegnali(SIGTERM, handler);
  setSegnali(SIGINT, handler);
}
void main(){
 eseguiSetSegnali(gestisciSIGNALDopoReg);
 sigprocmask(SIG_BLOCK,&mask,NULL);
 .........other part of code......... 
 sigprocmask(SIG_UNBLOCK,&mask,NULL);
}

пожалуйста! Мне нужна помощь!

1 ответ

Вы не инициализируете sa_flags поле вашего struct sigaction, так что он может содержать значения мусора. Возможно, что SA_RESETHAND бит установлен, который согласно man-странице даст вам такое поведение:

       SA_RESETHAND
              Restore the signal action to the default state once the signal handler has been called.  This flag  is
              only  meaningful  when establishing a signal handler.  SA_ONESHOT is an obsolete, non-standard synonym
              for this flag.

Если ваш обработчик сигнала запустился один раз, это привело бы к его очистке и возврату к значению по умолчанию, поэтому вам может понадобиться просто обнулить флаги, например:

void setSegnali(int segn,__sighandler_t handler){
  gestoreSegnale.sa_handler=handler;
  gestoreSegnale.sa_mask=mask;
  /* Make sure to clear flags */
  gestoreSegnale.sa_flags=0;

  sigaction(segn, &gestoreSegnale, NULL);
}

Во всяком случае, работает следующий маленький пример:

#include <signal.h>
#include <stdio.h>

void handler(int sig) {
    printf("HUP %d\n", sig);
}

void main(){
    struct sigaction act;

    /* Block SIGHUP while the signal handler is running */
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask,SIGHUP);

    /* Define handler for signal */
    act.sa_handler = handler;

    /* Clear flags */
    act.sa_flags = 0;
    act.sa_restorer = NULL;

    /* Install handler for SIGHUP */
    sigaction(SIGHUP, &act, NULL);

    /* Set mask to block SIGHUP */
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGHUP);

    /* Block SIGHUP */
    printf("Blocking SIGHUP\n");
    sigprocmask(SIG_BLOCK,&mask,NULL);
    printf("Sleeping\n");
    sleep(60);
    /* Unblock SIGHUP */
    printf("Unblocking SIGHUP\n");
    sigprocmask(SIG_UNBLOCK,&mask,NULL);
    printf("Sleeping again\n");
    while(1)
        sleep(60);
}

Если запустить, вы увидите желаемый результат:

$ ./sigtest 
Blocking SIGHUP
Sleeping             <-- SIGHUP sent from another terminal here but blocked
Unblocking SIGHUP
HUP 1                <-- Signal sent earlier now delivered and handled
Sleeping again
HUP 1                <-- Further signals sent are all handled
HUP 1
HUP 1
^C
Другие вопросы по тегам