[libc-commits] [libc] [libc] Implement sigtimedwait and sigwaitinfo in signal (PR #238000)
Leo Garcia via libc-commits
libc-commits at lists.llvm.org
Mon Nov 2 06:47:48 PST 2026
https://github.com/leogarci42 created https://github.com/llvm/llvm-project/pull/238000
Add the standard POSIX function sigtimedwait and sigwaitinfo to <signal.h>:
- Add low-level rt_sigtimedwait system call wrapper in libc/src/__support/OSUtil/linux/syscall_wrappers/rt_sigtimedwait.h.
- Add public header declaration in libc/src/signal/sigtimedwait.h.
- Implement sigtimedwait entrypoint in libc/src/signal/linux/sigtimedwait.cpp.
- Add public header declaration in libc/src/signal/sigwaitinfo.h.
- Implement sigwaitinfo entrypoint in libc/src/signal/linux/sigwaitinfo.cpp using rt_sigtimedwait with a null timeout.
- Declare sigtimedwait and sigwaitinfo in libc/include/signal.yaml.
- Register both entrypoints for Linux (x86_64, aarch64, riscv) in architecture config files.
- Update CMakeLists.txt files across syscall wrappers, signal sources, and tests.
- Add unit tests in libc/test/src/signal/sigtimedwait_test.cpp and libc/test/src/signal/sigwaitinfo_test.cpp.
Part of #236167
>From dcf63255ac15594e2bac67408f2bf0d6195d5eb3 Mon Sep 17 00:00:00 2001
From: leogarci42 <lg9752247 at gmail.com>
Date: Mon, 2 Nov 2026 14:54:47 +0100
Subject: [PATCH 1/2] Add the standard POSIX function sigtimedwait to
<signal.h>:
Add low-level rt_sigtimedwait system call wrapper in libc/src/__support/OSUtil/linux/syscall_wrappers/rt_sigtimedwait.h.
Add public header declaration in libc/src/signal/sigtimedwait.h.
Implement sigtimedwait entrypoint in libc/src/signal/linux/sigtimedwait.cpp.
Declare sigtimedwait and struct_timespec in libc/include/signal.yaml.
Define SYS_rt_sigtimedwait_time64 in libc/include/sys/syscall.h.def.
Register entrypoint for Linux (x86_64, aarch64, riscv) in architecture config files.
Update CMakeLists.txt files across syscall wrappers, signal sources, and tests.
Add unit tests in libc/test/src/signal/sigtimedwait_test.cpp.
Part of #236167
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/include/signal.yaml | 9 ++
libc/include/sys/syscall.h.def | 4 +
.../linux/syscall_wrappers/CMakeLists.txt | 15 +++
.../linux/syscall_wrappers/rt_sigtimedwait.h | 54 ++++++++
libc/src/signal/CMakeLists.txt | 7 +
libc/src/signal/linux/CMakeLists.txt | 14 ++
libc/src/signal/linux/sigtimedwait.cpp | 37 +++++
libc/src/signal/sigtimedwait.h | 29 ++++
libc/test/src/signal/CMakeLists.txt | 23 ++++
libc/test/src/signal/sigtimedwait_test.cpp | 126 ++++++++++++++++++
13 files changed, 321 insertions(+)
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/rt_sigtimedwait.h
create mode 100644 libc/src/signal/linux/sigtimedwait.cpp
create mode 100644 libc/src/signal/sigtimedwait.h
create mode 100644 libc/test/src/signal/sigtimedwait_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index b45313f5068bd0..64133615149f77 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1402,6 +1402,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.signal.sigismember
libc.src.signal.signal
libc.src.signal.sigprocmask
+ libc.src.signal.sigtimedwait
# spawn.h entrypoints
libc.src.spawn.posix_spawn
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 3b42f020cf750e..11e688351e12d6 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1588,6 +1588,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.signal.sigismember
libc.src.signal.signal
libc.src.signal.sigprocmask
+ libc.src.signal.sigtimedwait
# spawn.h entrypoints
libc.src.spawn.posix_spawn
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 0ec5d8f73a8a4d..2d7e600fd0c41a 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1614,6 +1614,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.signal.sigismember
libc.src.signal.signal
libc.src.signal.sigprocmask
+ libc.src.signal.sigtimedwait
# spawn.h entrypoints
libc.src.spawn.posix_spawn
diff --git a/libc/include/signal.yaml b/libc/include/signal.yaml
index b763da7eeb6025..a636c2f35bdf60 100644
--- a/libc/include/signal.yaml
+++ b/libc/include/signal.yaml
@@ -43,6 +43,7 @@ types:
- type_name: stack_t
- type_name: struct_sigaction
- type_name: struct_sigevent
+ - type_name: struct_timespec
- type_name: union_sigval
- type_name: pthread_t
standards:
@@ -127,6 +128,14 @@ functions:
- type: int
- type: const sigset_t *__restrict
- type: sigset_t *__restrict
+ - name: sigtimedwait
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: const sigset_t *__restrict
+ - type: siginfo_t *__restrict
+ - type: const struct timespec *__restrict
- name: pthread_sigmask
standards:
- posix
diff --git a/libc/include/sys/syscall.h.def b/libc/include/sys/syscall.h.def
index f3670a234c638f..5dce9077ddd6f4 100644
--- a/libc/include/sys/syscall.h.def
+++ b/libc/include/sys/syscall.h.def
@@ -1717,6 +1717,10 @@
#define SYS_rt_sigtimedwait __NR_rt_sigtimedwait
#endif
+#ifdef __NR_rt_sigtimedwait_time64
+#define SYS_rt_sigtimedwait_time64 __NR_rt_sigtimedwait_time64
+#endif
+
#ifdef __NR_rt_tgsigqueueinfo
#define SYS_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
#endif
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 117191eecb042f..bf2bb39de5637c 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -648,6 +648,21 @@ add_header_library(
libc.include.sys_syscall
)
+add_header_library(
+ rt_sigtimedwait
+ HDRS
+ rt_sigtimedwait.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.hdr.types.siginfo_t
+ libc.hdr.types.sigset_t
+ libc.hdr.types.struct_timespec
+ libc.include.sys_syscall
+)
+
add_header_library(
raise
HDRS
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/rt_sigtimedwait.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/rt_sigtimedwait.h
new file mode 100644
index 00000000000000..c5a45571d50d91
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/rt_sigtimedwait.h
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Syscall wrapper for rt_sigtimedwait.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_RT_SIGTIMEDWAIT_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_RT_SIGTIMEDWAIT_H
+
+#include "hdr/types/siginfo_t.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> rt_sigtimedwait(const sigset_t *set, siginfo_t *info,
+ const struct timespec *timeout) {
+#if defined(SYS_rt_sigtimedwait_time64)
+ static_assert(
+ sizeof(time_t) == sizeof(int64_t),
+ "SYS_rt_sigtimedwait_time64 requires struct timespec with 64-bit "
+ "members.");
+ return syscall_checked<int>(SYS_rt_sigtimedwait_time64, set, info, timeout,
+ sizeof(sigset_t));
+#elif defined(SYS_rt_sigtimedwait)
+ static_assert(
+ sizeof(timespec::tv_nsec) == sizeof(long),
+ "This legacy syscall fallback is only safe on platforms where tv_nsec "
+ "matches the register size (long). It is unsafe on 32-bit platforms "
+ "with 64-bit tv_nsec.");
+ return syscall_checked<int>(SYS_rt_sigtimedwait, set, info, timeout,
+ sizeof(sigset_t));
+#else
+#error "rt_sigtimedwait and rt_sigtimedwait_time64 syscalls not available."
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_RT_SIGTIMEDWAIT_H
diff --git a/libc/src/signal/CMakeLists.txt b/libc/src/signal/CMakeLists.txt
index 8da94d1eea85fd..fea8a43193b3e0 100644
--- a/libc/src/signal/CMakeLists.txt
+++ b/libc/src/signal/CMakeLists.txt
@@ -37,6 +37,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.sigprocmask
)
+add_entrypoint_object(
+ sigtimedwait
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sigtimedwait
+)
+
add_entrypoint_object(
pthread_sigmask
ALIAS
diff --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt
index 77898cf9aab636..6ba3c205ca391e 100644
--- a/libc/src/signal/linux/CMakeLists.txt
+++ b/libc/src/signal/linux/CMakeLists.txt
@@ -95,6 +95,20 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ sigtimedwait
+ SRCS
+ sigtimedwait.cpp
+ HDRS
+ ../sigtimedwait.h
+ DEPENDS
+ libc.hdr.types.siginfo_t
+ libc.hdr.types.sigset_t
+ libc.hdr.types.struct_timespec
+ libc.src.__support.OSUtil.linux.syscall_wrappers.rt_sigtimedwait
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
pthread_sigmask
SRCS
diff --git a/libc/src/signal/linux/sigtimedwait.cpp b/libc/src/signal/linux/sigtimedwait.cpp
new file mode 100644
index 00000000000000..bb48cf75632567
--- /dev/null
+++ b/libc/src/signal/linux/sigtimedwait.cpp
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Linux implementation of sigtimedwait.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/signal/sigtimedwait.h"
+
+#include "hdr/types/siginfo_t.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/rt_sigtimedwait.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sigtimedwait,
+ (const sigset_t *__restrict set, siginfo_t *__restrict info,
+ const struct timespec *__restrict timeout)) {
+ auto result = linux_syscalls::rt_sigtimedwait(set, info, timeout);
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return -1;
+ }
+ return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/signal/sigtimedwait.h b/libc/src/signal/sigtimedwait.h
new file mode 100644
index 00000000000000..d926b044c084ba
--- /dev/null
+++ b/libc/src/signal/sigtimedwait.h
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Implementation header for sigtimedwait.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SIGNAL_SIGTIMEDWAIT_H
+#define LLVM_LIBC_SRC_SIGNAL_SIGTIMEDWAIT_H
+
+#include "hdr/types/siginfo_t.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int sigtimedwait(const sigset_t *__restrict set, siginfo_t *__restrict info,
+ const struct timespec *__restrict timeout);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SIGNAL_SIGTIMEDWAIT_H
diff --git a/libc/test/src/signal/CMakeLists.txt b/libc/test/src/signal/CMakeLists.txt
index 287977e2762236..5695bbc74ddc23 100644
--- a/libc/test/src/signal/CMakeLists.txt
+++ b/libc/test/src/signal/CMakeLists.txt
@@ -54,6 +54,29 @@ add_libc_test(
libc.test.UnitTest.ErrnoSetterMatcher
)
+add_libc_test(
+ sigtimedwait_test
+ SUITE
+ libc-signal-tests
+ SRCS
+ sigtimedwait_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.signal_macros
+ libc.hdr.types.siginfo_t
+ libc.hdr.types.sigset_t
+ libc.hdr.types.struct_sigaction
+ libc.hdr.types.struct_timespec
+ libc.src.signal.raise
+ libc.src.signal.sigaction
+ libc.src.signal.sigaddset
+ libc.src.signal.sigemptyset
+ libc.src.signal.sigprocmask
+ libc.src.signal.sigtimedwait
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
+
add_libc_test(
pthread_sigmask_test
SUITE
diff --git a/libc/test/src/signal/sigtimedwait_test.cpp b/libc/test/src/signal/sigtimedwait_test.cpp
new file mode 100644
index 00000000000000..9375582a65bc81
--- /dev/null
+++ b/libc/test/src/signal/sigtimedwait_test.cpp
@@ -0,0 +1,126 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unittests for sigtimedwait.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/signal_macros.h"
+#include "hdr/types/siginfo_t.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/struct_sigaction.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/signal/raise.h"
+#include "src/signal/sigaction.h"
+#include "src/signal/sigaddset.h"
+#include "src/signal/sigemptyset.h"
+#include "src/signal/sigprocmask.h"
+#include "src/signal/sigtimedwait.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+static void test_sig_handler(int) {}
+
+class LlvmLibcSigtimedwaitTest
+ : public LIBC_NAMESPACE::testing::ErrnoCheckingTest {
+ struct sigaction old_action{};
+ sigset_t old_mask{};
+
+public:
+ void SetUp() override {
+ ErrnoCheckingTest::SetUp();
+ ASSERT_THAT(LIBC_NAMESPACE::sigprocmask(0, nullptr, &old_mask), Succeeds());
+
+ struct sigaction sa{};
+ sa.sa_handler = test_sig_handler;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&sa.sa_mask), Succeeds());
+ sa.sa_flags = 0;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGUSR1, &sa, &old_action),
+ Succeeds());
+
+ sigset_t blocked;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&blocked), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigaddset(&blocked, SIGUSR1), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigprocmask(SIG_BLOCK, &blocked, nullptr),
+ Succeeds());
+ }
+
+ void TearDown() override {
+ LIBC_NAMESPACE::sigprocmask(SIG_SETMASK, &old_mask, nullptr);
+ LIBC_NAMESPACE::sigaction(SIGUSR1, &old_action, nullptr);
+ ErrnoCheckingTest::TearDown();
+ }
+};
+
+// This tests that a pending signal is returned along with its info.
+TEST_F(LlvmLibcSigtimedwaitTest, PendingSignalReturnsSignalAndInfo) {
+ sigset_t set;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&set), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigaddset(&set, SIGUSR1), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::raise(SIGUSR1), Succeeds());
+
+ struct timespec timeout{0, 0};
+ siginfo_t info{};
+ ASSERT_THAT(LIBC_NAMESPACE::sigtimedwait(&set, &info, &timeout),
+ Succeeds(SIGUSR1));
+ EXPECT_EQ(info.si_signo, SIGUSR1);
+
+ EXPECT_THAT(LIBC_NAMESPACE::sigtimedwait(&set, nullptr, &timeout),
+ Fails(EAGAIN));
+}
+
+// This tests that a null info pointer is allowed.
+TEST_F(LlvmLibcSigtimedwaitTest, NullInfo) {
+ sigset_t set;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&set), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigaddset(&set, SIGUSR1), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::raise(SIGUSR1), Succeeds());
+
+ struct timespec timeout{0, 0};
+ ASSERT_THAT(LIBC_NAMESPACE::sigtimedwait(&set, nullptr, &timeout),
+ Succeeds(SIGUSR1));
+}
+
+// This tests that a null timeout waits until a pending signal arrives.
+TEST_F(LlvmLibcSigtimedwaitTest, NullTimeoutWithPendingSignal) {
+ sigset_t set;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&set), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigaddset(&set, SIGUSR1), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::raise(SIGUSR1), Succeeds());
+
+ siginfo_t info{};
+ ASSERT_THAT(LIBC_NAMESPACE::sigtimedwait(&set, &info, nullptr),
+ Succeeds(SIGUSR1));
+ EXPECT_EQ(info.si_signo, SIGUSR1);
+}
+
+// This tests that no pending signal with a zero timeout returns EAGAIN.
+TEST_F(LlvmLibcSigtimedwaitTest, NoPendingSignalTimesOut) {
+ sigset_t set;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&set), Succeeds());
+
+ struct timespec timeout{0, 0};
+ EXPECT_THAT(LIBC_NAMESPACE::sigtimedwait(&set, nullptr, &timeout),
+ Fails(EAGAIN));
+}
+
+// This tests that an invalid timeout returns EINVAL.
+TEST_F(LlvmLibcSigtimedwaitTest, InvalidTimeout) {
+ sigset_t set;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&set), Succeeds());
+
+ struct timespec timeout{0, 1000000000L};
+ EXPECT_THAT(LIBC_NAMESPACE::sigtimedwait(&set, nullptr, &timeout),
+ Fails(EINVAL));
+}
>From 1929baab2b4eaadb83fde3942ff2a31d45f437f4 Mon Sep 17 00:00:00 2001
From: leogarci42 <lg9752247 at gmail.com>
Date: Mon, 2 Nov 2026 15:14:22 +0100
Subject: [PATCH 2/2] Add the standard POSIX function sigwaitinfo to
<signal.h>:
Implement sigwaitinfo entrypoint in libc/src/signal/linux/sigwaitinfo.cpp.
Add public header declaration in libc/src/signal/sigwaitinfo.h.
Declare sigwaitinfo in libc/include/signal.yaml.
Reuse the existing rt_sigtimedwait system call wrapper.
Register entrypoint for Linux (x86_64, aarch64, riscv) in architecture config files.
Update CMakeLists.txt files across signal sources and tests.
Add unit tests in libc/test/src/signal/sigwaitinfo_test.cpp.
Part of #236167
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/include/signal.yaml | 7 ++
libc/src/signal/CMakeLists.txt | 7 ++
libc/src/signal/linux/CMakeLists.txt | 13 ++++
libc/src/signal/linux/sigwaitinfo.cpp | 36 +++++++++
libc/src/signal/sigwaitinfo.h | 27 +++++++
libc/test/src/signal/CMakeLists.txt | 22 ++++++
libc/test/src/signal/sigwaitinfo_test.cpp | 91 +++++++++++++++++++++++
10 files changed, 206 insertions(+)
create mode 100644 libc/src/signal/linux/sigwaitinfo.cpp
create mode 100644 libc/src/signal/sigwaitinfo.h
create mode 100644 libc/test/src/signal/sigwaitinfo_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 64133615149f77..55713606b198dd 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1403,6 +1403,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.signal.signal
libc.src.signal.sigprocmask
libc.src.signal.sigtimedwait
+ libc.src.signal.sigwaitinfo
# spawn.h entrypoints
libc.src.spawn.posix_spawn
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 11e688351e12d6..51803a59abdc97 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1589,6 +1589,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.signal.signal
libc.src.signal.sigprocmask
libc.src.signal.sigtimedwait
+ libc.src.signal.sigwaitinfo
# spawn.h entrypoints
libc.src.spawn.posix_spawn
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 2d7e600fd0c41a..b14d6369e1d4e7 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1615,6 +1615,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.signal.signal
libc.src.signal.sigprocmask
libc.src.signal.sigtimedwait
+ libc.src.signal.sigwaitinfo
# spawn.h entrypoints
libc.src.spawn.posix_spawn
diff --git a/libc/include/signal.yaml b/libc/include/signal.yaml
index a636c2f35bdf60..76b36808979b27 100644
--- a/libc/include/signal.yaml
+++ b/libc/include/signal.yaml
@@ -136,6 +136,13 @@ functions:
- type: const sigset_t *__restrict
- type: siginfo_t *__restrict
- type: const struct timespec *__restrict
+ - name: sigwaitinfo
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: const sigset_t *__restrict
+ - type: siginfo_t *__restrict
- name: pthread_sigmask
standards:
- posix
diff --git a/libc/src/signal/CMakeLists.txt b/libc/src/signal/CMakeLists.txt
index fea8a43193b3e0..db22d042551bfa 100644
--- a/libc/src/signal/CMakeLists.txt
+++ b/libc/src/signal/CMakeLists.txt
@@ -44,6 +44,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.sigtimedwait
)
+add_entrypoint_object(
+ sigwaitinfo
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sigwaitinfo
+)
+
add_entrypoint_object(
pthread_sigmask
ALIAS
diff --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt
index 6ba3c205ca391e..17a1bda355c61b 100644
--- a/libc/src/signal/linux/CMakeLists.txt
+++ b/libc/src/signal/linux/CMakeLists.txt
@@ -109,6 +109,19 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ sigwaitinfo
+ SRCS
+ sigwaitinfo.cpp
+ HDRS
+ ../sigwaitinfo.h
+ DEPENDS
+ libc.hdr.types.siginfo_t
+ libc.hdr.types.sigset_t
+ libc.src.__support.OSUtil.linux.syscall_wrappers.rt_sigtimedwait
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
pthread_sigmask
SRCS
diff --git a/libc/src/signal/linux/sigwaitinfo.cpp b/libc/src/signal/linux/sigwaitinfo.cpp
new file mode 100644
index 00000000000000..11b14170f348ad
--- /dev/null
+++ b/libc/src/signal/linux/sigwaitinfo.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Linux implementation of sigwaitinfo.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/signal/sigwaitinfo.h"
+
+#include "hdr/types/siginfo_t.h"
+#include "hdr/types/sigset_t.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/rt_sigtimedwait.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sigwaitinfo,
+ (const sigset_t *__restrict set,
+ siginfo_t *__restrict info)) {
+ auto result = linux_syscalls::rt_sigtimedwait(set, info, nullptr);
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return -1;
+ }
+ return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/signal/sigwaitinfo.h b/libc/src/signal/sigwaitinfo.h
new file mode 100644
index 00000000000000..585f81190a77a4
--- /dev/null
+++ b/libc/src/signal/sigwaitinfo.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Implementation header for sigwaitinfo.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SIGNAL_SIGWAITINFO_H
+#define LLVM_LIBC_SRC_SIGNAL_SIGWAITINFO_H
+
+#include "hdr/types/siginfo_t.h"
+#include "hdr/types/sigset_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int sigwaitinfo(const sigset_t *__restrict set, siginfo_t *__restrict info);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SIGNAL_SIGWAITINFO_H
diff --git a/libc/test/src/signal/CMakeLists.txt b/libc/test/src/signal/CMakeLists.txt
index 5695bbc74ddc23..4ebdeccad83b1a 100644
--- a/libc/test/src/signal/CMakeLists.txt
+++ b/libc/test/src/signal/CMakeLists.txt
@@ -77,6 +77,28 @@ add_libc_test(
libc.test.UnitTest.ErrnoSetterMatcher
)
+add_libc_test(
+ sigwaitinfo_test
+ SUITE
+ libc-signal-tests
+ SRCS
+ sigwaitinfo_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.signal_macros
+ libc.hdr.types.siginfo_t
+ libc.hdr.types.sigset_t
+ libc.hdr.types.struct_sigaction
+ libc.src.signal.raise
+ libc.src.signal.sigaction
+ libc.src.signal.sigaddset
+ libc.src.signal.sigemptyset
+ libc.src.signal.sigprocmask
+ libc.src.signal.sigwaitinfo
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
+
add_libc_test(
pthread_sigmask_test
SUITE
diff --git a/libc/test/src/signal/sigwaitinfo_test.cpp b/libc/test/src/signal/sigwaitinfo_test.cpp
new file mode 100644
index 00000000000000..86be0da3d9fe49
--- /dev/null
+++ b/libc/test/src/signal/sigwaitinfo_test.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unittests for sigwaitinfo.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/signal_macros.h"
+#include "hdr/types/siginfo_t.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/struct_sigaction.h"
+#include "src/signal/raise.h"
+#include "src/signal/sigaction.h"
+#include "src/signal/sigaddset.h"
+#include "src/signal/sigemptyset.h"
+#include "src/signal/sigprocmask.h"
+#include "src/signal/sigwaitinfo.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+static void test_sig_handler(int) {}
+
+class LlvmLibcSigwaitinfoTest
+ : public LIBC_NAMESPACE::testing::ErrnoCheckingTest {
+ struct sigaction old_action{};
+ sigset_t old_mask{};
+
+public:
+ void SetUp() override {
+ ErrnoCheckingTest::SetUp();
+ ASSERT_THAT(LIBC_NAMESPACE::sigprocmask(0, nullptr, &old_mask), Succeeds());
+
+ struct sigaction sa{};
+ sa.sa_handler = test_sig_handler;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&sa.sa_mask), Succeeds());
+ sa.sa_flags = 0;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGUSR1, &sa, &old_action),
+ Succeeds());
+
+ sigset_t blocked;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&blocked), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigaddset(&blocked, SIGUSR1), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigprocmask(SIG_BLOCK, &blocked, nullptr),
+ Succeeds());
+ }
+
+ void TearDown() override {
+ LIBC_NAMESPACE::sigprocmask(SIG_SETMASK, &old_mask, nullptr);
+ LIBC_NAMESPACE::sigaction(SIGUSR1, &old_action, nullptr);
+ ErrnoCheckingTest::TearDown();
+ }
+};
+
+// This tests that a pending signal is returned along with its info.
+TEST_F(LlvmLibcSigwaitinfoTest, PendingSignalReturnsSignalAndInfo) {
+ sigset_t set;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&set), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigaddset(&set, SIGUSR1), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::raise(SIGUSR1), Succeeds());
+
+ siginfo_t info{};
+ ASSERT_THAT(LIBC_NAMESPACE::sigwaitinfo(&set, &info), Succeeds(SIGUSR1));
+ EXPECT_EQ(info.si_signo, SIGUSR1);
+}
+
+// This tests that a null info pointer is allowed.
+TEST_F(LlvmLibcSigwaitinfoTest, NullInfo) {
+ sigset_t set;
+ ASSERT_THAT(LIBC_NAMESPACE::sigemptyset(&set), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sigaddset(&set, SIGUSR1), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::raise(SIGUSR1), Succeeds());
+
+ ASSERT_THAT(LIBC_NAMESPACE::sigwaitinfo(&set, nullptr), Succeeds(SIGUSR1));
+}
+
+// This tests that a null set pointer returns EFAULT.
+TEST_F(LlvmLibcSigwaitinfoTest, NullSet) {
+ siginfo_t info{};
+ EXPECT_THAT(LIBC_NAMESPACE::sigwaitinfo(nullptr, &info), Fails(EFAULT));
+}
More information about the libc-commits
mailing list