[libc-commits] [libc] [llvm] [libc] Move linux signal mask helpers into OSUtil/sigmask.h (PR #232647)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Fri Oct 16 01:45:35 PDT 2026


https://github.com/labath created https://github.com/llvm/llvm-project/pull/232647

Move internal signal set and mask helpers (full_set, empty_set, add, remove, block_all, set_mask, etc.) out of signal_utils.h and into a new src/__support/OSUtil/linux/sigmask.h header under the signals namespace. This allows other low-level OS utilities and entrypoints to manipulate signal masks without pulling in signal_utils.h (defined under src/signal).

The rest of signal_utils.h should also move, but I'm leaving that for a separate PR (and a separate file) because the rest of the file has more dependencies (RwLock, vdso, __restore_rt), and interacts with more components.

Along with the move:
- fix full_set() on 32-bit systems: sigset_t{{-1UL}} only set the first word, leaving real-time signals unmasked. Now we loop over __signals.
- rename the helpers to shorter names within the signals namespace (add_signal -> add, delete_signal -> remove, restore_signals -> set_mask, etc.) and update existing callers in signal_utils, abort_utils, sigaddset, sigdelset, sigemptyset, and sigfillset.
- add block and get_mask helpers and migrate call sites in sigsetjmp_epilogue and system.

Assisted-by: Gemini

>From de4a5e0d1ae5d32cadb06de59b1b44e8ccf78e66 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Fri, 16 Oct 2026 08:13:51 +0000
Subject: [PATCH] [libc] Move linux signal mask helpers into OSUtil/sigmask.h

Move internal signal set and mask helpers (full_set, empty_set, add,
remove, block_all, set_mask, etc.) out of signal_utils.h and into a new
src/__support/OSUtil/linux/sigmask.h header under the signals namespace.
This allows other low-level OS utilities and entrypoints to manipulate
signal masks without pulling in signal_utils.h (defined under
src/signal).

The rest of signal_utils.h should also move, but I'm leaving that for a
separate PR (and a separate file) because the rest of the file has more
dependencies (RwLock, vdso, __restore_rt), and interacts with more
components.

Along with the move:
- fix full_set() on 32-bit systems: sigset_t{{-1UL}} only set the first
  word, leaving real-time signals unmasked. Now we loop over __signals.
- rename the helpers to shorter names within the signals namespace
  (add_signal -> add, delete_signal -> remove, restore_signals ->
  set_mask, etc.) and update existing callers in signal_utils,
  abort_utils, sigaddset, sigdelset, sigemptyset, and sigfillset.
- add block and get_mask helpers and migrate call sites in
  sigsetjmp_epilogue and system.

Assisted-by: Gemini
---
 .../src/__support/OSUtil/linux/CMakeLists.txt |  15 +++
 libc/src/__support/OSUtil/linux/sigmask.h     | 122 ++++++++++++++++++
 libc/src/setjmp/linux/CMakeLists.txt          |   2 +-
 libc/src/setjmp/linux/sigsetjmp_epilogue.cpp  |  13 +-
 libc/src/signal/linux/CMakeLists.txt          |  10 +-
 libc/src/signal/linux/sigaddset.cpp           |   4 +-
 libc/src/signal/linux/sigdelset.cpp           |   4 +-
 libc/src/signal/linux/sigemptyset.cpp         |   4 +-
 libc/src/signal/linux/sigfillset.cpp          |   4 +-
 libc/src/signal/linux/signal_utils.h          |  52 +-------
 libc/src/stdlib/linux/CMakeLists.txt          |   3 +-
 libc/src/stdlib/linux/abort_utils.h           |   4 +-
 libc/src/stdlib/linux/system.cpp              |  14 +-
 libc/test/src/signal/sigfillset_test.cpp      |   9 +-
 .../llvm-project-overlay/libc/BUILD.bazel     |  24 +++-
 15 files changed, 198 insertions(+), 86 deletions(-)
 create mode 100644 libc/src/__support/OSUtil/linux/sigmask.h

diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index e01f079c6780e5..22004c234650c7 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -66,6 +66,21 @@ add_header_library(
     libc.src.__support.CPP.string_view
 )
 
+add_header_library(
+  sigmask
+  HDRS
+    sigmask.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.signal_macros
+    libc.hdr.types.sigset_t
+    libc.hdr.types.size_t
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.src.__support.OSUtil.linux.syscall_wrappers.rt_sigprocmask
+)
+
 add_header_library(
   sysinfo
   HDRS
diff --git a/libc/src/__support/OSUtil/linux/sigmask.h b/libc/src/__support/OSUtil/linux/sigmask.h
new file mode 100644
index 00000000000000..25ade4a1f3aea4
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/sigmask.h
@@ -0,0 +1,122 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Internal Linux signal mask helpers.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_SIGMASK_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_SIGMASK_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/signal_macros.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/size_t.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/rt_sigprocmask.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace signals {
+
+static constexpr size_t BITS_PER_SIGWORD = sizeof(unsigned long) * 8;
+
+/// Return a signal set with all signals set.
+LIBC_INLINE constexpr sigset_t full_set() {
+  sigset_t set{};
+  for (unsigned long &sigword : set.__signals)
+    sigword = -1UL;
+  return set;
+}
+
+/// Return an empty signal set with no signals set.
+LIBC_INLINE constexpr sigset_t empty_set() { return sigset_t{}; }
+
+/// Set or clear the bit corresponding to |signal| in |set| according to
+/// |value|. Return true on success and false if |signal| is out of range.
+LIBC_INLINE constexpr bool set_bit(sigset_t &set, int signal, bool value) {
+  if (signal >= NSIG || signal <= 0)
+    return false;
+  size_t n = static_cast<size_t>(signal) - 1;
+  size_t word = n / BITS_PER_SIGWORD;
+  size_t bit = n % BITS_PER_SIGWORD;
+  if (value)
+    set.__signals[word] |= (1UL << bit);
+  else
+    set.__signals[word] &= ~(1UL << bit);
+  return true;
+}
+
+/// Set the bit corresponding to |signal| in |set|. Return true on success
+/// and false on failure. |signal| must be less than NSIG and be positive.
+LIBC_INLINE constexpr bool add(sigset_t &set, int signal) {
+  return set_bit(set, signal, true);
+}
+
+/// Clear the bit corresponding to |signal| in |set|. Return true on success
+/// and false on failure. |signal| must be less than NSIG and be positive.
+LIBC_INLINE constexpr bool remove(sigset_t &set, int signal) {
+  return set_bit(set, signal, false);
+}
+
+/// Block the signals in |set|. If |old_set| is non-null, store the previous
+/// signal mask in |*old_set|.
+LIBC_INLINE ErrorOr<int> block(const sigset_t &set,
+                               sigset_t *old_set = nullptr) {
+  return linux_syscalls::rt_sigprocmask(SIG_BLOCK, &set, old_set);
+}
+
+/// Block a single |signal|. If |old_set| is non-null, store the previous
+/// signal mask in |*old_set|.
+LIBC_INLINE ErrorOr<int> block(int signal, sigset_t *old_set = nullptr) {
+  sigset_t set = empty_set();
+  if (!add(set, signal))
+    return Error(EINVAL);
+  return block(set, old_set);
+}
+
+/// Block all signals. If |old_set| is non-null, store the previous signal mask
+/// in |*old_set|.
+LIBC_INLINE ErrorOr<int> block_all(sigset_t *old_set = nullptr) {
+  return block(full_set(), old_set);
+}
+
+/// Set the signal mask to |set|. If |old_set| is non-null, store the previous
+/// signal mask in |*old_set|.
+LIBC_INLINE ErrorOr<int> set_mask(const sigset_t &set,
+                                  sigset_t *old_set = nullptr) {
+  return linux_syscalls::rt_sigprocmask(SIG_SETMASK, &set, old_set);
+}
+
+/// Store the current signal mask in |set|.
+LIBC_INLINE ErrorOr<int> get_mask(sigset_t &set) {
+  return linux_syscalls::rt_sigprocmask(SIG_SETMASK, nullptr, &set);
+}
+
+/// Unblock the signals in |set|. If |old_set| is non-null, store the previous
+/// signal mask in |*old_set|.
+LIBC_INLINE ErrorOr<int> unblock(const sigset_t &set,
+                                 sigset_t *old_set = nullptr) {
+  return linux_syscalls::rt_sigprocmask(SIG_UNBLOCK, &set, old_set);
+}
+
+/// Unblock a single |signal|. If |old_set| is non-null, store the previous
+/// signal mask in |*old_set|.
+LIBC_INLINE ErrorOr<int> unblock(int signal, sigset_t *old_set = nullptr) {
+  sigset_t set = empty_set();
+  if (!add(set, signal))
+    return Error(EINVAL);
+  return unblock(set, old_set);
+}
+
+} // namespace signals
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_SIGMASK_H
diff --git a/libc/src/setjmp/linux/CMakeLists.txt b/libc/src/setjmp/linux/CMakeLists.txt
index bde4e5b87392bf..215145729f270f 100644
--- a/libc/src/setjmp/linux/CMakeLists.txt
+++ b/libc/src/setjmp/linux/CMakeLists.txt
@@ -6,7 +6,7 @@ add_object_library(
     sigsetjmp_epilogue.cpp
   DEPENDS
     libc.src.__support.common
-    libc.src.__support.OSUtil.linux.syscall_wrappers.rt_sigprocmask
+    libc.src.__support.OSUtil.linux.sigmask
     libc.hdr.types.sigjmp_buf
     libc.hdr.types.sigset_t
 )
diff --git a/libc/src/setjmp/linux/sigsetjmp_epilogue.cpp b/libc/src/setjmp/linux/sigsetjmp_epilogue.cpp
index 7922f51225f3c0..176deaaa654e66 100644
--- a/libc/src/setjmp/linux/sigsetjmp_epilogue.cpp
+++ b/libc/src/setjmp/linux/sigsetjmp_epilogue.cpp
@@ -7,18 +7,15 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/setjmp/sigsetjmp_epilogue.h"
-#include "src/__support/OSUtil/linux/syscall_wrappers/rt_sigprocmask.h"
+#include "src/__support/OSUtil/linux/sigmask.h"
 #include "src/__support/common.h"
 
 namespace LIBC_NAMESPACE_DECL {
 [[gnu::returns_twice]] int sigsetjmp_epilogue(sigjmp_buf buffer, int retval) {
-  // If set is NULL, then the signal mask is unchanged (i.e., how is
-  // ignored), but the current value of the signal mask is nevertheless
-  // returned in oldset (if it is not NULL).
-  linux_syscalls::rt_sigprocmask(
-      SIG_SETMASK,
-      /* set= */ retval ? &buffer->sigmask : nullptr,
-      /* old_set= */ retval ? nullptr : &buffer->sigmask);
+  if (retval)
+    signals::set_mask(buffer->sigmask);
+  else
+    signals::get_mask(buffer->sigmask);
   return retval;
 }
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt
index 8360ce21364766..c035a4915e132f 100644
--- a/libc/src/signal/linux/CMakeLists.txt
+++ b/libc/src/signal/linux/CMakeLists.txt
@@ -10,7 +10,7 @@ add_header_library(
     libc.include.sys_syscall
     libc.src.__support.OSUtil.linux.vdso
     libc.src.__support.OSUtil.osutil
-    libc.src.__support.OSUtil.linux.syscall_wrappers.rt_sigprocmask
+    libc.src.__support.OSUtil.linux.sigmask
     libc.src.__support.error_or
     libc.src.__support.threads.raw_rwlock
 )
@@ -131,8 +131,8 @@ add_entrypoint_object(
   HDRS
     ../sigemptyset.h
   DEPENDS
-    .signal_utils
     libc.hdr.types.sigset_t
+    libc.src.__support.OSUtil.linux.sigmask
     libc.src.errno.errno
 )
 
@@ -143,8 +143,8 @@ add_entrypoint_object(
   HDRS
     ../sigaddset.h
   DEPENDS
-    .signal_utils
     libc.hdr.types.sigset_t
+    libc.src.__support.OSUtil.linux.sigmask
     libc.src.errno.errno
 )
 
@@ -166,8 +166,8 @@ add_entrypoint_object(
   HDRS
     ../sigfillset.h
   DEPENDS
-    .signal_utils
     libc.hdr.types.sigset_t
+    libc.src.__support.OSUtil.linux.sigmask
     libc.src.errno.errno
 )
 
@@ -178,7 +178,7 @@ add_entrypoint_object(
   HDRS
     ../sigdelset.h
   DEPENDS
-    .signal_utils
     libc.hdr.types.sigset_t
+    libc.src.__support.OSUtil.linux.sigmask
     libc.src.errno.errno
 )
diff --git a/libc/src/signal/linux/sigaddset.cpp b/libc/src/signal/linux/sigaddset.cpp
index 2091e8b51453fb..2372d4a8654d44 100644
--- a/libc/src/signal/linux/sigaddset.cpp
+++ b/libc/src/signal/linux/sigaddset.cpp
@@ -9,15 +9,15 @@
 #include "src/signal/sigaddset.h"
 
 #include "hdr/types/sigset_t.h"
+#include "src/__support/OSUtil/linux/sigmask.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
-#include "src/signal/linux/signal_utils.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, sigaddset, (sigset_t * set, int signum)) {
-  if (set != nullptr && add_signal(*set, signum))
+  if (set != nullptr && signals::add(*set, signum))
     return 0;
   libc_errno = EINVAL;
   return -1;
diff --git a/libc/src/signal/linux/sigdelset.cpp b/libc/src/signal/linux/sigdelset.cpp
index 6fce0d7a6e1474..36b4df3024d363 100644
--- a/libc/src/signal/linux/sigdelset.cpp
+++ b/libc/src/signal/linux/sigdelset.cpp
@@ -9,15 +9,15 @@
 #include "src/signal/sigdelset.h"
 
 #include "hdr/types/sigset_t.h"
+#include "src/__support/OSUtil/linux/sigmask.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
-#include "src/signal/linux/signal_utils.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, sigdelset, (sigset_t * set, int signum)) {
-  if (set != nullptr && delete_signal(*set, signum))
+  if (set != nullptr && signals::remove(*set, signum))
     return 0;
   libc_errno = EINVAL;
   return -1;
diff --git a/libc/src/signal/linux/sigemptyset.cpp b/libc/src/signal/linux/sigemptyset.cpp
index 788983f429baa0..d80a3186bc234e 100644
--- a/libc/src/signal/linux/sigemptyset.cpp
+++ b/libc/src/signal/linux/sigemptyset.cpp
@@ -7,10 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/signal/sigemptyset.h"
+#include "src/__support/OSUtil/linux/sigmask.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
-#include "src/signal/linux/signal_utils.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(int, sigemptyset, (sigset_t * set)) {
     libc_errno = EINVAL;
     return -1;
   }
-  *set = empty_set();
+  *set = signals::empty_set();
   return 0;
 }
 
diff --git a/libc/src/signal/linux/sigfillset.cpp b/libc/src/signal/linux/sigfillset.cpp
index f0b499093b3198..cc8c9b7dd09e88 100644
--- a/libc/src/signal/linux/sigfillset.cpp
+++ b/libc/src/signal/linux/sigfillset.cpp
@@ -9,10 +9,10 @@
 #include "src/signal/sigfillset.h"
 
 #include "hdr/types/sigset_t.h"
+#include "src/__support/OSUtil/linux/sigmask.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
-#include "src/signal/linux/signal_utils.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -21,7 +21,7 @@ LLVM_LIBC_FUNCTION(int, sigfillset, (sigset_t * set)) {
     libc_errno = EINVAL;
     return -1;
   }
-  *set = full_set();
+  *set = signals::full_set();
   return 0;
 }
 
diff --git a/libc/src/signal/linux/signal_utils.h b/libc/src/signal/linux/signal_utils.h
index 7a78b00d865de6..07b89e8e921289 100644
--- a/libc/src/signal/linux/signal_utils.h
+++ b/libc/src/signal/linux/signal_utils.h
@@ -14,7 +14,7 @@
 #include "hdr/types/sigset_t.h"
 #include "hdr/types/size_t.h"
 #include "hdr/types/struct_sigaction.h"
-#include "src/__support/OSUtil/linux/syscall_wrappers/rt_sigprocmask.h"
+#include "src/__support/OSUtil/linux/sigmask.h"
 #include "src/__support/OSUtil/linux/vdso.h"
 #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
 #include "src/__support/common.h"
@@ -72,52 +72,6 @@ struct KernelSigaction {
   sigset_t sa_mask;
 };
 
-static constexpr size_t BITS_PER_SIGWORD = sizeof(unsigned long) * 8;
-
-LIBC_INLINE constexpr sigset_t full_set() { return sigset_t{{-1UL}}; }
-
-LIBC_INLINE constexpr sigset_t empty_set() { return sigset_t{{0}}; }
-
-// Set the bit corresponding to |signal| in |set|. Return true on success
-// and false on failure. |signal| must be less than NSIG and be positive.
-LIBC_INLINE constexpr bool add_signal(sigset_t &set, int signal) {
-  if (signal >= NSIG || signal <= 0)
-    return false;
-  size_t n = size_t(signal) - 1;
-  size_t word = n / BITS_PER_SIGWORD;
-  size_t bit = n % BITS_PER_SIGWORD;
-  set.__signals[word] |= (1UL << bit);
-  return true;
-}
-
-// Reset the bit corresponding to |signal| in |set|. Return true on success
-// and false on failure. |signal| must be less than NSIG and be positive.
-LIBC_INLINE constexpr bool delete_signal(sigset_t &set, int signal) {
-  if (signal >= NSIG || signal <= 0)
-    return false;
-  size_t n = size_t(signal) - 1;
-  size_t word = n / BITS_PER_SIGWORD;
-  size_t bit = n % BITS_PER_SIGWORD;
-  set.__signals[word] &= ~(1UL << bit);
-  return true;
-}
-
-LIBC_INLINE ErrorOr<int> block_all_signals(sigset_t &set) {
-  sigset_t full = full_set();
-  return linux_syscalls::rt_sigprocmask(SIG_BLOCK, &full, &set);
-}
-
-LIBC_INLINE ErrorOr<int> restore_signals(const sigset_t &set) {
-  return linux_syscalls::rt_sigprocmask(SIG_SETMASK, &set, nullptr);
-}
-
-LIBC_INLINE ErrorOr<int> unblock_signal(int signal) {
-  sigset_t set = empty_set();
-  if (!add_signal(set, signal))
-    return Error(EINVAL);
-  return linux_syscalls::rt_sigprocmask(SIG_UNBLOCK, &set, nullptr);
-}
-
 // This guard is used to:
 // 1. temporarily block the all signal, avoid post fork invalid state to be
 //    exposed to async signal handlers.
@@ -140,13 +94,13 @@ class SigAbortGuard {
 
     // This uses a valid sigset_t size and internal storage. A failure here
     // would indicate a kernel ABI mismatch, which is not actionable here.
-    (void)block_all_signals(old_mask);
+    (void)signals::block_all(&old_mask);
   }
 
   LIBC_INLINE ~SigAbortGuard() {
     // This restores a previously saved mask from internal storage. A failure
     // here would likewise be a non-recoverable kernel ABI issue.
-    (void)restore_signals(old_mask);
+    (void)signals::set_mask(old_mask);
     (void)abort_lock.unlock();
   }
 };
diff --git a/libc/src/stdlib/linux/CMakeLists.txt b/libc/src/stdlib/linux/CMakeLists.txt
index c40fc6a5b84ce7..f0dff355f5789d 100644
--- a/libc/src/stdlib/linux/CMakeLists.txt
+++ b/libc/src/stdlib/linux/CMakeLists.txt
@@ -3,6 +3,7 @@ add_header_library(
   HDRS
     abort_utils.h
   DEPENDS
+    libc.src.__support.OSUtil.linux.sigmask
     libc.src.__support.OSUtil.linux.syscall_wrappers.raise
     libc.src.__support.OSUtil.osutil
     libc.src.signal.linux.__restore
@@ -122,10 +123,10 @@ add_entrypoint_object(
     libc.src.__support.libc_errno
     libc.src.__support.macros.config
     libc.src.__support.OSUtil.osutil
+    libc.src.__support.OSUtil.linux.sigmask
     libc.src.__support.OSUtil.linux.syscall_wrappers.execle
     libc.src.__support.OSUtil.linux.syscall_wrappers.clone3
     libc.src.__support.OSUtil.linux.syscall_wrappers.rt_sigaction
-    libc.src.__support.OSUtil.linux.syscall_wrappers.rt_sigprocmask
     libc.src.__support.OSUtil.linux.syscall_wrappers.wait4
     libc.src.signal.linux.signal_utils
     libc.src.unistd.environ
diff --git a/libc/src/stdlib/linux/abort_utils.h b/libc/src/stdlib/linux/abort_utils.h
index 9ba752ed252bb7..b7a42d7dda824e 100644
--- a/libc/src/stdlib/linux/abort_utils.h
+++ b/libc/src/stdlib/linux/abort_utils.h
@@ -9,9 +9,9 @@
 #ifndef LLVM_LIBC_SRC_STDLIB_LINUX_ABORT_UTILS_H
 #define LLVM_LIBC_SRC_STDLIB_LINUX_ABORT_UTILS_H
 
-#include "hdr/types/sigset_t.h"
 #include "hdr/types/struct_sigaction.h"
 #include "src/__support/OSUtil/exit.h"
+#include "src/__support/OSUtil/linux/sigmask.h"
 #include "src/__support/OSUtil/linux/syscall_wrappers/raise.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
@@ -43,7 +43,7 @@ namespace abort_utils {
   // Now unblock the signal. The pending abort signal is now unblocked and
   // should be delivered to its default handler.
   // If this fails, there is still no meaningful recovery path while aborting.
-  (void)unblock_signal(SIGABRT);
+  (void)signals::unblock(SIGABRT);
 
   internal::exit(127);
 }
diff --git a/libc/src/stdlib/linux/system.cpp b/libc/src/stdlib/linux/system.cpp
index f40e1f8756b155..f80987633bdcb0 100644
--- a/libc/src/stdlib/linux/system.cpp
+++ b/libc/src/stdlib/linux/system.cpp
@@ -17,10 +17,10 @@
 #include "hdr/types/pid_t.h"
 #include "hdr/types/sigset_t.h"
 #include "src/__support/OSUtil/exit.h"
+#include "src/__support/OSUtil/linux/sigmask.h"
 #include "src/__support/OSUtil/linux/syscall_wrappers/clone3.h"
 #include "src/__support/OSUtil/linux/syscall_wrappers/execle.h"
 #include "src/__support/OSUtil/linux/syscall_wrappers/rt_sigaction.h"
-#include "src/__support/OSUtil/linux/syscall_wrappers/rt_sigprocmask.h"
 #include "src/__support/OSUtil/linux/syscall_wrappers/wait4.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
@@ -57,12 +57,8 @@ LLVM_LIBC_FUNCTION(int, system, (const char *command)) {
     return -1;
   }
 
-  sigset_t block_mask{};
-  add_signal(block_mask, SIGCHLD);
   sigset_t orig_mask{};
-  if (auto res =
-          linux_syscalls::rt_sigprocmask(SIG_BLOCK, &block_mask, &orig_mask);
-      !res.has_value()) {
+  if (auto res = signals::block(SIGCHLD, &orig_mask); !res.has_value()) {
     linux_syscalls::rt_sigaction(SIGINT, &orig_int, nullptr);
     linux_syscalls::rt_sigaction(SIGQUIT, &orig_quit, nullptr);
     libc_errno = res.error();
@@ -75,7 +71,7 @@ LLVM_LIBC_FUNCTION(int, system, (const char *command)) {
   if (!fork_res.has_value()) {
     linux_syscalls::rt_sigaction(SIGINT, &orig_int, nullptr);
     linux_syscalls::rt_sigaction(SIGQUIT, &orig_quit, nullptr);
-    linux_syscalls::rt_sigprocmask(SIG_SETMASK, &orig_mask, nullptr);
+    signals::set_mask(orig_mask);
     libc_errno = fork_res.error();
     return -1;
   }
@@ -84,7 +80,7 @@ LLVM_LIBC_FUNCTION(int, system, (const char *command)) {
   if (pid == 0) {
     linux_syscalls::rt_sigaction(SIGINT, &orig_int, nullptr);
     linux_syscalls::rt_sigaction(SIGQUIT, &orig_quit, nullptr);
-    linux_syscalls::rt_sigprocmask(SIG_SETMASK, &orig_mask, nullptr);
+    signals::set_mask(orig_mask);
 
     // Error checking isn't helpful since this is the forked process, so we
     // can't set errno. All we can meaningfully do is exit with status 127.
@@ -110,7 +106,7 @@ LLVM_LIBC_FUNCTION(int, system, (const char *command)) {
 
   linux_syscalls::rt_sigaction(SIGINT, &orig_int, nullptr);
   linux_syscalls::rt_sigaction(SIGQUIT, &orig_quit, nullptr);
-  linux_syscalls::rt_sigprocmask(SIG_SETMASK, &orig_mask, nullptr);
+  signals::set_mask(orig_mask);
 
   return wait_ret;
 }
diff --git a/libc/test/src/signal/sigfillset_test.cpp b/libc/test/src/signal/sigfillset_test.cpp
index 1f69734404e18a..b1074987f2bd2f 100644
--- a/libc/test/src/signal/sigfillset_test.cpp
+++ b/libc/test/src/signal/sigfillset_test.cpp
@@ -25,5 +25,12 @@ TEST(LlvmLibcSigfillset, BlocksAll) {
   EXPECT_THAT(LIBC_NAMESPACE::sigfillset(&set), Succeeds());
   EXPECT_THAT(LIBC_NAMESPACE::sigprocmask(SIG_SETMASK, &set, nullptr),
               Succeeds());
-  EXPECT_EXITS([] { LIBC_NAMESPACE::raise(SIGUSR1); }, 0);
+  EXPECT_EXITS(
+      [] {
+        LIBC_NAMESPACE::raise(SIGUSR1);
+#ifdef SIGRTMAX
+        LIBC_NAMESPACE::raise(SIGRTMAX);
+#endif
+      },
+      0);
 }
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 457de6f7048762..43bb5b522823c0 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -4380,6 +4380,26 @@ libc_support_library(
     }),
 )
 
+libc_support_library(
+    name = "__support_osutil_linux_sigmask",
+    hdrs = ["src/__support/OSUtil/linux/sigmask.h"],
+    full_build_only = True,
+    target_compatible_with = select({
+        "@platforms//os:linux": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    deps = [
+        ":__support_common",
+        ":__support_error_or",
+        ":__support_macros_config",
+        ":__support_osutil_linux_syscall_wrappers_rt_sigprocmask",
+        ":hdr_errno_macros",
+        ":hdr_signal_macros",
+        ":types_sigset_t",
+        ":types_size_t",
+    ],
+)
+
 libc_support_library(
     name = "__support_stringutil",
     srcs = glob(["src/__support/StringUtil/tables/**/*.h"]) + [
@@ -15801,8 +15821,8 @@ libc_support_library(
         ":__support_common",
         ":__support_macros_config",
         ":__support_osutil_exit",
+        ":__support_osutil_linux_sigmask",
         ":__support_osutil_linux_syscall_wrappers_raise",
-        ":types_sigset_t",
         ":types_struct_sigaction",
     ],
 )
@@ -17168,7 +17188,7 @@ libc_support_library(
         ":__support_common",
         ":__support_error_or",
         ":__support_macros_config",
-        ":__support_osutil_linux_syscall_wrappers_rt_sigprocmask",
+        ":__support_osutil_linux_sigmask",
         ":__support_osutil_syscall",
         ":__support_osutil_vdso",
         ":__support_threads_raw_rwlock",



More information about the libc-commits mailing list