Search code examples
linuxsignalssignal-handlingsigactionsigprocmask

Signals in the "set" parameter of sigtimedwait() not getting delivered


I have been working on signal handling on Linux lately, and have read all the concepts related to signal handling. One question that's tinkering my head is that why the signal in the set of sigtimedwait() doesn't get delivered while the process is unblocked. My code is as follows :-

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
void sighandler1(int sig)
{
        printf("SIGINT caught\n");
}
void sighandler2(int sig)
{
        printf("SIGTSTP caught\n");
}
void sighandler3(int sig)
{
        printf("SIGALRM caught\n");
}

int main()
{

  sigset_t s1,s2;

  struct sigaction act1,act2,act3;

  int ret;

  sigemptyset(&s1);// The bit-mask s1 is cleared
  sigaddset(&s1,SIGINT);//Add SIGINT to the bit-mask s1

  sigemptyset(&s2);// The bit-mask s2 is cleared
  sigaddset(&s2,SIGALRM);//Add SIGALRM to the bit-mask s2

  sigprocmask(SIG_BLOCK,&s2,NULL);//Signal(s) in s2 blocked

  act1.sa_handler = sighandler1; //function pointer pointing to the signal handler
  act1.sa_flags = 0;        

  sigaction(SIGINT,&act1,NULL);  // installing the action
                                 // for SIGINT

  act2.sa_handler = sighandler2; //function pointer pointing to another signal handler
  act2.sa_flags = 0;         // no flags


  sigaction(SIGTSTP,&act2,NULL);  // installing the action
                                 // for SIGTSTP
  act3.sa_handler = sighandler3; //function pointer pointing to another signal handler
  act3.sa_flags = 0;         // no flags


  sigaction(SIGALRM,&act3,NULL);  // installing the action for SIGALRM

  sigprocmask(SIG_SETMASK,&s1,NULL); //Signals in s1 blocked and other signals unblocked
  printf("sigprocmask() called with SIG_SETMASK on s1,which contains SIGINT\n");
  printf("Blocked on sigtimedwait() with s1\n");
  if(sigtimedwait(&s1,NULL,NULL) < 0)
        {
                if(errno ==  EINTR)
                printf("Some other signal caught\n");
        }
  printf("This is a process. You can pass signal to it\n");

  while(1);

}

To be more clear with the question, I have called sigtimedwait in the above code with "s1" as the "set "parameter . This set contains only the signal SIGINT. As per the man page, sigtimedwait() blocks the process , until one of the signals in its set is delivered. I am all okay with that statement. But Why is the SIGINT handler not called when I pass SIGINT to unblock the process? On the other hand, when I pass SIGALRM or SIGTSTP, which are not there in the set, EINTR is returned as expected, and also the signal handler gets called.

For anyone, who wants to observe the scenario, can execute the above code and then pass SIGINT to it. They will observe that the process is unblocked without the handler being called . Why is the handler not called? Am I misinterpreting any part of the man page of sigtimedwait()??


Solution

  • sigtimedwait seems to return the signal value, instead of the signal handler getting caught:

    switch(sigtimedwait(&s1,NULL,NULL))
    {
        default:
            printf ("Some other signal???");
            break;
        case SIGINT:
            printf ("We got SIGINT\n");
            break;
        case -1:
            perror ("sigtimedwait");
            break;
    }