If no signal in
set is pending at the time of the call, the thread shall be
suspended until one or more becomes
pending. The signals defined by set
shall have been blocked at the
time of the call to sigwait(); otherwise, the behavior is undefined.
The effect of sigwait() on the signal
actions for the signals in set is
unspecified.
This is really ambiguous ,what's the difference between pending
and block
here?
And its conclusion on how to choose between sigwait
and sigaction
is not clear at all:
In summary, when it is necessary for
code run in response to an
asynchronous signal to notify a
thread, sigwait() should be used to
handle the signal. Alterna-
tively, if the implementation provides semaphores, they also can be
used, either following sigwait() or
from within a signal handling routine
previously registered
with sigaction().
Can someone make the reason of sigwait
more rational?
Every process has what's called a signal mask associated with it, which defines the set of signals which are blocked. The signal mask can be queried or set with setprocmask(2)
(for single-threaded code) and pthread_sigmask(3)
(for multithreaded code).
Whenever a signal is raised (either explicitly via kill(2)
or raise(3)
, or via some other mechanism such as a segmentation fault raising SIGSEGV
), the signal is checked against the current signal mask. If the signal is not blocked, then it is acted upon immediately: the corresponding signal handler is called if set, otherwise the default action (typically exiting with abnormal status or ignoring it) is run. If the signal is blocked by the signal mask, then the state of the signal is set to pending, and the program continues execution.
So consider the following example program:
#include <signal.h>
#include <stdio.h>
void on_sigusr1(int sig)
{
// Note: Normally, it's not safe to call almost all library functions in a
// signal handler, since the signal may have been received in a middle of a
// call to that function.
printf("SIGUSR1 received!\n");
}
int main(void)
{
// Set a signal handler for SIGUSR1
signal(SIGUSR1, &on_sigusr1);
// At program startup, SIGUSR1 is neither blocked nor pending, so raising it
// will call the signal handler
raise(SIGUSR1);
// Now let's block SIGUSR1
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sigset, NULL);
// SIGUSR1 is now blocked, raising it will not call the signal handler
printf("About to raise SIGUSR1\n");
raise(SIGUSR1);
printf("After raising SIGUSR1\n");
// SIGUSR1 is now blocked and pending -- this call to sigwait will return
// immediately
int sig;
int result = sigwait(&sigset, &sig);
if(result == 0)
printf("sigwait got signal: %d\n", sig);
// SIGUSR1 is now no longer pending (but still blocked). Raise it again and
// unblock it
raise(SIGUSR1);
printf("About to unblock SIGUSR1\n");
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
printf("Unblocked SIGUSR1\n");
return 0;
}
Output:
SIGUSR1 received!
About to raise SIGUSR1
After raising SIGUSR1
sigwait got signal: 30
About to unblock SIGUSR1
SIGUSR1 received!
Unblocked SIGUSR1
From the signal(7)
man page:
Signal Mask and Pending Signals
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated and
when it is delivered a signal is said to be pending.
"Pending" and "blocked" are not mutually exclusive.
Also from the signal(7)
man page:
Synchronously Accepting a Signal
Rather than asynchronously catching a signal via a signal handler, it
is possible to synchronously accept the signal, that is, to block exe-
cution until the signal is delivered, at which point the kernel returns
information about the signal to the caller. There are two general ways
to do this:
* sigwaitinfo(2), sigtimedwait(2), and sigwait(3) suspend execution
until one of the signals in a specified set is delivered. Each of
these calls returns information about the delivered signal.
So sigaction()
is used to allow other code to run until a signal is pending, whereas sigwait()
suspends execution of the thread until a signal is pending but blocked.