sigprocmask(2)

๐Ÿ’– sigprocmask โ€” bestie edition ๐Ÿ’–

okay so this is sigprocmask(2), and yes it lives in the System Calls Manual, but honestly it's more like the group chat settings for your signals. grab a snack, we're learning signal masks ๐Ÿ“


โœจ NAME โœจ

sigprocmask, rt_sigprocmask โ€” examine and change blocked signals

๐Ÿ“š LIBRARY ๐Ÿ“š

Standard C library (libc, -lc) โ€” she's a libc girlie ๐Ÿ’…

๐ŸŒธ SYNOPSIS ๐ŸŒธ

#include <signal.h>

/* Prototype for the glibc wrapper function */
int sigprocmask(int how, const sigset_t *_Nullable restrict set,
                           sigset_t *_Nullable restrict oldset);

#include <signal.h>           /* Definition of SIG_* constants */
#include <sys/syscall.h>      /* Definition of SYS_* constants */
#include <unistd.h>

/* Prototype for the underlying system call */
int syscall(SYS_rt_sigprocmask, int how,
                           const kernel_sigset_t *_Nullable set,
                           kernel_sigset_t *_Nullable oldset,
                           size_t sigsetsize);

/* Prototype for the legacy system call */
[[deprecated]] int syscall(SYS_sigprocmask, int how,
                           const old_kernel_sigset_t *_Nullable set,
                           old_kernel_sigset_t *_Nullable oldset);

๐ŸŽ€ Feature Test Macro Requirements for glibc ๐ŸŽ€

(see feature_test_macros(7), iykyk)

  • sigprocmask(): _POSIX_C_SOURCE

๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

sigprocmask() is the function you call to fetch and/or change the signal mask of the calling thread โ€” no cap. And what's the signal mask, bestie? It's literally the set of signals whose delivery is currently blocked for whoever's calling (peep signal(7) for the full tea ๐Ÿ’€).

The way the call behaves totally depends on how, and here's the breakdown:

  • SIG_BLOCK โ€” the set of blocked signals becomes the union of the current set and the set argument. union, slay โœจ
  • SIG_UNBLOCK โ€” the signals in set get removed from the current set of blocked signals. and yes, it is totally permissible to attempt to unblock a signal that isn't even blocked. no gatekeeping here ๐Ÿซถ
  • SIG_SETMASK โ€” the set of blocked signals is just set to the set argument. periodt.

If oldset is non-NULL, the previous value of the signal mask gets stored in oldset. lil time capsule moment ๐Ÿ“ฆ

And if set is NULL? then the signal mask stays unchanged (like, how is fully ignored, not even looked at), but the current value of the signal mask is still returned in oldset (as long as oldset isn't NULL). iconique behaviour tbh.

There's a whole squad of functions for modifying and inspecting variables of type sigset_t โ€” aka "signal sets" โ€” and they're described over in sigsetops(3).

โš ๏ธ heads up: using sigprocmask() in a multithreaded process is unspecified. it's giving chaos. go see pthread_sigmask(3) instead, fr fr.

๐Ÿ”ฅ RETURN VALUE ๐Ÿ”ฅ

sigprocmask() returns 0 on success. On failure, -1 comes back and errno is set to tell you what went wrong. she said "here's your error code, you're welcome" ๐Ÿ˜ญ

๐Ÿ’€ ERRORS ๐Ÿ’€

  • EFAULT โ€” the set or oldset argument points outside the process's allocated address space. ma'am that is NOT your memory ๐Ÿ’…
  • EINVAL โ€” either the value specified in how was invalid, or the kernel does not support the size passed in sigsetsize. nope, rejected ๐Ÿ™ˆ

๐ŸŒˆ VERSIONS ๐ŸŒˆ

๐Ÿงš C library/kernel differences ๐Ÿงš

okay this part is lowkey important so listen up:

The kernel's definition of sigset_t differs in size from the one the C library uses. In this manual page, the kernel's version is referred to as kernel_sigset_t โ€” although it is nevertheless named sigset_t in the kernel sources. two things, same name, different sizes ๐Ÿ’€

The glibc wrapper function for sigprocmask() silently ignores attempts to block the two real-time signals that are used internally by the NPTL threading implementation. sneaky! see nptl(7) for details.

The original Linux system call was named sigprocmask(). But then real-time signals showed up in Linux 2.2, and the fixed-size, 32-bit sigset_t (called old_kernel_sigset_t in this manual page) that the old system call supported was no longer fit for purpose โ€” it just couldn't serve the look anymore. So a new system call, rt_sigprocmask(), was added to support an enlarged sigset_t type (referred to as kernel_sigset_t in this manual page). The new system call takes a fourth argument, size_t sigsetsize, which specifies the size in bytes of the signal sets in set and oldset. This argument is currently required to have a fixed architecture specific value (equal to sizeof(kernel_sigset_t)). no flexibility, sorry bestie, it's architecture-locked ๐Ÿ”’

And the glibc sigprocmask() wrapper function hides all of these details from us, transparently calling rt_sigprocmask() whenever the kernel provides it. she's doing the work behind the scenes, main character energy ๐Ÿ‘‘

๐Ÿ‘‘ STANDARDS ๐Ÿ‘‘

POSIX.1-2024.

๐ŸŽ€ HISTORY ๐ŸŽ€

POSIX.1-2001.

๐ŸŒŸ NOTES ๐ŸŒŸ

  • It is not possible to block SIGKILL or SIGSTOP. attempts to do so are silently ignored. you cannot stop these two, they said no ๐Ÿ’€
  • Each of the threads in a process has its own signal mask. everybody's got their own vibe ๐Ÿฆ‹
  • A child created via fork(2) inherits a copy of its parent's signal mask; and the signal mask is preserved across execve(2). family heirloom behaviour tbh ๐Ÿ’–
  • If SIGBUS, SIGFPE, SIGILL, or SIGSEGV are generated while they are blocked, the result is undefined, unless the signal was generated by kill(2), sigqueue(3), or raise(3). undefined = we do not know what happens. do not test this. i am begging ๐Ÿ™ˆ
  • See sigsetops(3) for details on manipulating signal sets.
  • Note that it is permissible (although not very useful) to specify both set and oldset as NULL. technically allowed! practically pointless! that's the whole note! ๐Ÿ˜ญ

๐Ÿ’œ SEE ALSO ๐Ÿ’œ

kill(2), pause(2), sigaction(2), signal(2), sigpending(2), sigsuspend(2), pthread_sigmask(3), sigqueue(3), sigsetops(3), signal(7)


and that's the whole page bestie, you ate that ๐Ÿ’…โœจ

this edition came from Linux man-pages 6.20, dated 2026-02-08, and it's still sigprocmask(2) at heart โ€” go block some signals responsibly, mwah ๐Ÿซถ๐ŸŽ€

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms