Signal Mask

Every thread has a signal mask — a bitmask of signals currently blocked. A blocked signal is not delivered to the thread; it remains in the pending set until unblocked. Changed with sigprocmask(2) (per-process) or pthread_sigmask(3) (per-thread).

sigset_t mask, old;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigprocmask(SIG_BLOCK, &mask, &old);   // block SIGINT
/* critical section — SIGINT deferred */
sigprocmask(SIG_SETMASK, &old, NULL);  // restore

Why it matters

  • Critical sections: blocking a signal around code that must not be interrupted atomically
  • Thread signal routing: in a multi-threaded program, only one thread will receive a given signal; the conventional pattern is to block signals in all threads except one dedicated signal handler thread
  • pselect(): atomically unblocks a signal set and waits — the only race-free way to wait for both I/O and signals

Relationship to delivery

A signal can be: ignored (handler is SIG_IGN), blocked (in mask, deferred), caught (custom handler), or handled by the default action (typically terminate or stop). Blocking ≠ ignoring: a blocked signal is remembered and delivered when unblocked.

In the curriculum

Covered in m07-processes-signals lesson 7-4 (“Signals”) and the PDF ch08 Key Concepts table. The PDF Going Deeper section includes the pending/blocked state diagram and the self-pipe trick.

See also

signals, threads, fork