I haven't completely understood, how to use sigprocmask()
. Particularly, how the set
and oldset
and its syntax work and how to use them.
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
Please explain with an example, to block, say SIGUSR1 for a few seconds and then unblock and handle it.
The sigprocmask() function examines, or changes, or both examines and changes the signal mask of the calling thread. The signals SIGKILL or SIGStop cannot be blocked.
sigprocmask() is used to fetch and/or change the signal mask of the calling thread. The signal mask is the set of signals whose delivery is currently blocked for the caller (see also signal(7) for more details). The behavior of the call is dependent on the value of how, as follows.
The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent's mask. You can block or unblock signals with total flexibility by modifying the signal mask.
SIGSEGV is an MMU (virtual memory hardware) exception. SIGSEGV does not necessarily imply that any UB occurred, it only means you tried to access memory that isn't mapped. The reason you can't block it is because after the signal is raised the program retries the same operation that caused the problem.
The idea is that you provide a mask in set
, effectively a list of signals. The how
argument says what you should do with the mask in set
.
You can either use SIG_BLOCK
to block the signals in the set
list, or SIG_UNBLOCK
to unblock them. Neither of these changes the signals that aren't set in the list. SIG_SETMASK
blocks the signals in the list, and unblocks the ones that aren't set in the list.
For instance, assume that the old blocking list was {SIGSEGV, SIGSUSP}
and you call sigprocmask
with these arguments:
sigset_t x; sigemptyset (&x); sigaddset(&x, SIGUSR1); sigprocmask(SIG_BLOCK, &x, NULL)
The new blocking list will now be {SIGSEGV, SIGSUSP, SIGUSR1}
.
If you call sigprocmask
with these arguments now:
sigprocmask(SIG_UNBLOCK, &x, NULL)
The new blocking list will go back to being {SIGSEGV, SIGSUSP}
.
If you call sigprocmask
with these arguments now:
sigprocmask(SIG_SETMASK, &x, NULL)
The new blocking list will now be set to {SIGUSR1}
.
The oldset
argument tells you what the previous blocking list was. If we have this declaration:
sigset_t y;
and we call the code in the previous examples like this:
sigprocmask(SIG_BLOCK, &x, &y)
now we have:
y == {SIGSEGV, SIGSUSP}
If we now do:
sigprocmask(SIG_UNBLOCK, &x, &y)
we'll get
y == {SIGSEGV, SIGSUSP, SIGUSR1}
and if we do:
sigprocmask(SIG_SET, &x, &y)
we'll get this:
y == {SIGSEGV, SIGSUSP}
because this is the previous value of the blocking set.
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