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?
You are doing 2 things here:
Populating a sigset_t
. A sigset_t is just a collection of values for signals, and are used in various system calls. You can:
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.
Signals sets are manipulated via sigset_t
type. Several operations are available for signals sets:
sigemptyset
, S=∅sigaddset
, S=S∪{s}sigdelset
, S=S\{s}sigfillset
.sigismember
, s∈S?Such a set is used at different places: setting a new process signal mask, blocking set during signal handling, requesting the set of pending signals, etc.
If you want to catch different signals, it may appears that some catching functions must not be interrupted with others, so you can add a set of signals to be blocked during the delivery of a given signal. You actually decided (when uncommented) to block SIGINT during SIGALRM delivery. So you can only observe this by sending a SIGINT during the execution of the handler; which is difficult to realize.
A example where it can be important ?
Suppose that the handler of SIGUSR1 modify a given data structure and that the handler for SIGUSR2 uses that same data structure. It is very important to make both handlers not concurrent, one can be run after the other but you probably don't want to be interrupted by one during the delivery of the other. Your code is self-concurrent, say that even in the case of only one thread, signals can lead you to concurrency.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With