What is sigaddset used for?

I have this code where I use sigaddset and sigaction. However, if I comment on segaddset, the result will be 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 it?

+5
source share
3 answers

You do 2 things here:

  • Filling a sigset_t . Sigset_t is just a set of values ​​for signals and is used in various system calls. You can:

    • Create an empty sigset_t (sigemptyset () file
    • Add signal to set (sigaddset ())
    • Delete signal on set (sigdelset ())
    • etc...
  • Setting the signal mask for the signal handler. You do this by manipulating the sigset_t sa_mask struct sigaction when you set up a signal handler with a call to sigaction ().

The signal mask of the signal handler means that during the execution of the signal handler, the signals that are in the mask will be blocked, that is, these signals will not be processed until they are blocked. When the signal handler is finished, the signals in will be unlocked. A signal that is blocked is not “lost”, it will be processed when this particular signal is unblocked again.

sigaddset(&act.sa_mask, SIGINT); means that the SIGINT signal cannot appear when the code for the SIGALRM handler is executed.

On the other hand, if you comment out sigaddset(&act.sa_mask, SIGINT); , you will only have an empty list of signals created using sigemptyset(&act.sa_mask); . Thus, any signals that occur during the operation of the SIGALRM handler can supplant this handler and execute a signal handler for this other signal.

For SIGINT, you usually don’t notice any difference with manual testing - it is unlikely that you will hit CTRL-C exactly when your SIGALRM handler is running, and your SIGALRM handler is probably fast enough for you to not notice, SIGINT was a little delayed.

+12
source

Signal sets are processed using the sigset_t type. There are several operations available for signal sets:

  • create an empty set S via sigemptyset , S = ∅
  • add signal s to set S via sigaddset , S = S∪ {s}
  • remove signal s from the set via sigdelset , S = S \ {s}
  • create a set of all possible signals through sigfillset .
  • test is the signal s in the given set S through sigismember , s∈S?

This set is used in different places: setting a new process signal mask, blocking the set during signal processing, requesting a set of waiting signals, etc.

If you want to catch different signals, it might seem that some capture functions should not be interrupted by others, so you can add a set of signals that will be blocked during the delivery of a given signal. In fact, you decided (when uncommenting) to block SIGINT during SIGALRM delivery. Thus, you can only observe this by sending SIGINT at runtime; which is hard to understand.

An example where this might be important?

Suppose that the handler SIGUSR1 modifies this data structure and that the handler for SIGUSR2 uses the same data structure. It is very important that both handlers are not parallel, you can run after the other, but you probably do not want to be interrupted by one during the delivery of the other. Your code is self-consistent, let's say that even in the case of only one thread, signals can lead you to concurrency.

+5
source

sigaddset is used to add the appropriate signal mask to this sigset_t variable.

In sigaction, this is not required. You can use this when using sigprocmask, which is designed to block the signal that we mention in this variable.

0
source

Source: https://habr.com/ru/post/1208028/


All Articles