What is sigaddset used for?

NeDark picture NeDark · Dec 1, 2014 · Viewed 8.4k times · Source

I have this code where I use sigaddset and sigaction. However if I comment segaddset the result is the same

   struct sigaction act; 

   act.sa_handler = process_alarm; 
   act.sa_flags = 0;           
   sigemptyset(&act.sa_mask); 
   //sigaddset(&act.sa_mask, SIGINT); 

   sigaction(SIGALRM, &act, NULL);

   for(;;) 
   { 
      alarm(3); 
      pause();  
   } 

Why do I need to use it?

Answer

nos picture nos · Dec 1, 2014

You are doing 2 things here:

  1. Populating a sigset_t. A sigset_t is just a collection of values for signals, and are used in various system calls. You can:

    • Create an empty sigset_t (sigemptyset()
    • Add a signal to the set (sigaddset())
    • Remove a signal to the set (sigdelset())
    • etc...
  2. Setting the signal mask for the signal handler. You do that by manipulating the sigset_t sa_mask member of the struct sigaction when you set up a signal handler in with a call to sigaction().

The signal mask of a signal handler means that while the signal handler is executing, the signals that are in the mask will be blocked - i.e. those signals will not be handled as long as they are blocked. When the signal handler are finished, the signals in will be unblocked. A signal that is blocked isn't "lost", it will be handled when that particular signal is unblocked again.

The sigaddset(&act.sa_mask, SIGINT); means the the SIGINT signal cannot occur while the code for the SIGALRM handler is running.

On the other hand, if you comment out sigaddset(&act.sa_mask, SIGINT);, you're left with just an empty list of signals created with sigemptyset(&act.sa_mask);. So any signals that occur while the SIGALRM handler function is running might preempt that handler and execute the signal handler for that other signal.

For a SIGINT, you would normally not notice any difference with manual testing - it's unlikely you manage to hit CTRL-C exactly when your handler for SIGALRM is running, and your SIGALRM handler probably runs quickly enough that you would not notice if the SIGINT was slightly delayed.