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!
");
}
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
");
raise(SIGUSR1);
printf("After raising SIGUSR1
");
// 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
", sig);
// SIGUSR1 is now no longer pending (but still blocked). Raise it again and
// unblock it
raise(SIGUSR1);
printf("About to unblock SIGUSR1
");
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
printf("Unblocked SIGUSR1
");
return 0;
}
Output:
SIGUSR1 received!
About to raise SIGUSR1
After raising SIGUSR1
sigwait got signal: 30
About to unblock SIGUSR1
SIGUSR1 received!
Unblocked SIGUSR1
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…