[libc-commits] [libc] [libc] Port wait4 to the syscall_wrappers ladder (PR #218699)
Mikhail R. Gadelha via libc-commits
libc-commits at lists.llvm.org
Tue Aug 25 07:43:16 PDT 2026
https://github.com/mikhailramalho created https://github.com/llvm/llvm-project/pull/218699
wait4Impl.h carried its own SYS_wait4/SYS_waitid fallback while syscall_wrappers/wait4.h assumed SYS_wait4 exists, so the wrapper failed to build on architectures that only provide waitid, such as rv32.
It should fix the rv32 bot.
>From 96ea97b2bebe02e7910341d87b400de63dcf59ac Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Tue, 25 Aug 2026 11:41:12 -0300
Subject: [PATCH] [libc] Port wait4 to the syscall_wrappers ladder
wait4Impl.h carried its own SYS_wait4/SYS_waitid fallback while
syscall_wrappers/wait4.h assumed SYS_wait4 exists, so the wrapper failed
to build on architectures that only provide waitid, such as rv32.
---
.../linux/syscall_wrappers/CMakeLists.txt | 3 +
.../OSUtil/linux/syscall_wrappers/wait4.h | 63 +++++++++++++
libc/src/sys/wait/linux/CMakeLists.txt | 18 +---
libc/src/sys/wait/linux/wait.cpp | 5 +-
libc/src/sys/wait/linux/wait4.cpp | 5 +-
libc/src/sys/wait/linux/waitpid.cpp | 5 +-
libc/src/sys/wait/wait4Impl.h | 91 -------------------
7 files changed, 78 insertions(+), 112 deletions(-)
delete mode 100644 libc/src/sys/wait/wait4Impl.h
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index e01f2a5789e37..98841113fc674 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -985,7 +985,10 @@ add_header_library(
HDRS
wait4.h
DEPENDS
+ libc.hdr.signal_macros
+ libc.hdr.sys_wait_macros
libc.hdr.types.pid_t
+ libc.hdr.types.siginfo_t
libc.hdr.types.struct_rusage
libc.src.__support.OSUtil.osutil
libc.src.__support.common
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/wait4.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/wait4.h
index 30d19ebae65f2..ac17b93166ac5 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/wait4.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/wait4.h
@@ -14,7 +14,10 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_WAIT4_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_WAIT4_H
+#include "hdr/signal_macros.h"
+#include "hdr/sys_wait_macros.h"
#include "hdr/types/pid_t.h"
+#include "hdr/types/siginfo_t.h"
#include "hdr/types/struct_rusage.h"
#include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
#include "src/__support/common.h"
@@ -27,7 +30,67 @@ namespace linux_syscalls {
LIBC_INLINE ErrorOr<pid_t> wait4(pid_t pid, int *wstatus, int options,
struct rusage *rusage) {
+#ifdef SYS_wait4
return syscall_checked<pid_t>(SYS_wait4, pid, wstatus, options, rusage);
+#elif defined(SYS_waitid)
+ // Architectures without wait4 (e.g. riscv32) provide waitid instead.
+ int idtype = P_PID;
+ if (pid == -1) {
+ idtype = P_ALL;
+ } else if (pid < -1) {
+ idtype = P_PGID;
+ pid *= -1;
+ } else if (pid == 0) {
+ idtype = P_PGID;
+ }
+
+ options |= WEXITED;
+
+ // Linux always writes si_pid and si_signo (see SYSCALL_DEFINE5(waitid) in
+ // kernel/exit.c), zeroing them when WNOHANG found nothing, so si_pid is a
+ // reliable "was anything reaped" flag. Initialize it anyway: POSIX only
+ // requires this since POSIX.1-2008 TC1.
+ siginfo_t info;
+ info.si_pid = 0;
+ auto result =
+ syscall_checked<pid_t>(SYS_waitid, idtype, pid, &info, options, rusage);
+ if (!result.has_value())
+ return result;
+
+ // WNOHANG with nothing to reap. Return 0 without touching wstatus, which is
+ // what wait4 does; falling through would clobber it via the default case.
+ if (info.si_pid == 0)
+ return 0;
+
+ if (wstatus) {
+ switch (info.si_code) {
+ case CLD_EXITED:
+ *wstatus = W_EXITCODE(info.si_status, 0);
+ break;
+ case CLD_DUMPED:
+ *wstatus = info.si_status | WCOREFLAG;
+ break;
+ case CLD_KILLED:
+ *wstatus = info.si_status;
+ break;
+ case CLD_TRAPPED:
+ case CLD_STOPPED:
+ *wstatus = W_STOPCODE(info.si_status);
+ break;
+ case CLD_CONTINUED:
+ // Set wstatus to a value that the caller can check via WIFCONTINUED.
+ // glibc has a non-POSIX macro definition __W_CONTINUED for this value.
+ *wstatus = 0xffff;
+ break;
+ default:
+ *wstatus = 0;
+ break;
+ }
+ }
+ return info.si_pid;
+#else
+#error "wait4 and waitid syscalls not available."
+#endif
}
} // namespace linux_syscalls
diff --git a/libc/src/sys/wait/linux/CMakeLists.txt b/libc/src/sys/wait/linux/CMakeLists.txt
index 207c3acc5df92..90a98b8c6f437 100644
--- a/libc/src/sys/wait/linux/CMakeLists.txt
+++ b/libc/src/sys/wait/linux/CMakeLists.txt
@@ -5,13 +5,9 @@ add_entrypoint_object(
HDRS
../wait.h
DEPENDS
- libc.hdr.signal_macros
- libc.hdr.sys_wait_macros
libc.hdr.types.pid_t
- libc.hdr.types.siginfo_t
libc.hdr.types.struct_rusage
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.wait4
libc.src.errno.errno
)
@@ -22,13 +18,9 @@ add_entrypoint_object(
HDRS
../wait4.h
DEPENDS
- libc.hdr.signal_macros
- libc.hdr.sys_wait_macros
libc.hdr.types.pid_t
- libc.hdr.types.siginfo_t
libc.hdr.types.struct_rusage
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.wait4
libc.src.errno.errno
)
@@ -39,12 +31,8 @@ add_entrypoint_object(
HDRS
../waitpid.h
DEPENDS
- libc.hdr.signal_macros
- libc.hdr.sys_wait_macros
libc.hdr.types.pid_t
- libc.hdr.types.siginfo_t
libc.hdr.types.struct_rusage
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.wait4
libc.src.errno.errno
)
diff --git a/libc/src/sys/wait/linux/wait.cpp b/libc/src/sys/wait/linux/wait.cpp
index dc97d0a4ff172..020766e4e77f0 100644
--- a/libc/src/sys/wait/linux/wait.cpp
+++ b/libc/src/sys/wait/linux/wait.cpp
@@ -6,17 +6,18 @@
//
//===----------------------------------------------------------------------===//
+#include "src/__support/OSUtil/linux/syscall_wrappers/wait4.h"
#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/sys/wait/wait.h"
-#include "src/sys/wait/wait4Impl.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(pid_t, wait, (int *wait_status)) {
- auto result = internal::wait4impl(-1, wait_status, 0, 0);
+ auto result = linux_syscalls::wait4(-1, wait_status, 0, nullptr);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
diff --git a/libc/src/sys/wait/linux/wait4.cpp b/libc/src/sys/wait/linux/wait4.cpp
index ac6d16933dc87..c398967e7c424 100644
--- a/libc/src/sys/wait/linux/wait4.cpp
+++ b/libc/src/sys/wait/linux/wait4.cpp
@@ -6,19 +6,20 @@
//
//===----------------------------------------------------------------------===//
+#include "src/__support/OSUtil/linux/syscall_wrappers/wait4.h"
#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/sys/wait/wait4.h"
-#include "src/sys/wait/wait4Impl.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(pid_t, wait4,
(pid_t pid, int *wait_status, int options,
struct rusage *usage)) {
- auto result = internal::wait4impl(pid, wait_status, options, usage);
+ auto result = linux_syscalls::wait4(pid, wait_status, options, usage);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
diff --git a/libc/src/sys/wait/linux/waitpid.cpp b/libc/src/sys/wait/linux/waitpid.cpp
index cb763a686353d..c5d9dd97d99d0 100644
--- a/libc/src/sys/wait/linux/waitpid.cpp
+++ b/libc/src/sys/wait/linux/waitpid.cpp
@@ -6,17 +6,18 @@
//
//===----------------------------------------------------------------------===//
+#include "src/__support/OSUtil/linux/syscall_wrappers/wait4.h"
#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
-#include "src/sys/wait/wait4Impl.h"
#include "src/sys/wait/waitpid.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(pid_t, waitpid, (pid_t pid, int *wait_status, int options)) {
- auto result = internal::wait4impl(pid, wait_status, options, 0);
+ auto result = linux_syscalls::wait4(pid, wait_status, options, nullptr);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
diff --git a/libc/src/sys/wait/wait4Impl.h b/libc/src/sys/wait/wait4Impl.h
deleted file mode 100644
index 984363a6682a7..0000000000000
--- a/libc/src/sys/wait/wait4Impl.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//===-- String to integer conversion utils ----------------------*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIBC_SRC_SYS_WAIT_WAIT4IMPL_H
-#define LLVM_LIBC_SRC_SYS_WAIT_WAIT4IMPL_H
-
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
-#include "src/__support/common.h"
-#include "src/__support/error_or.h"
-#include "src/__support/libc_errno.h"
-#include "src/__support/macros/config.h"
-
-#include "hdr/signal_macros.h"
-#include "hdr/sys_wait_macros.h"
-#include "hdr/types/pid_t.h"
-#include "hdr/types/siginfo_t.h"
-#include "hdr/types/struct_rusage.h"
-#include <sys/syscall.h> // For syscall numbers.
-
-namespace LIBC_NAMESPACE_DECL {
-namespace internal {
-
-// The implementation of wait here is very minimal. We will add more
-// functionality and standard compliance in future.
-
-LIBC_INLINE ErrorOr<pid_t> wait4impl(pid_t pid, int *wait_status, int options,
- struct rusage *usage) {
-#if SYS_wait4
- pid = LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_wait4, pid, wait_status,
- options, usage);
-#elif defined(SYS_waitid)
- int idtype = P_PID;
- if (pid == -1) {
- idtype = P_ALL;
- } else if (pid < -1) {
- idtype = P_PGID;
- pid *= -1;
- } else if (pid == 0) {
- idtype = P_PGID;
- }
-
- options |= WEXITED;
-
- siginfo_t info;
- pid = LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_waitid, idtype, pid, &info,
- options, usage);
- if (pid >= 0)
- pid = info.si_pid;
-
- if (wait_status) {
- switch (info.si_code) {
- case CLD_EXITED:
- *wait_status = W_EXITCODE(info.si_status, 0);
- break;
- case CLD_DUMPED:
- *wait_status = info.si_status | WCOREFLAG;
- break;
- case CLD_KILLED:
- *wait_status = info.si_status;
- break;
- case CLD_TRAPPED:
- case CLD_STOPPED:
- *wait_status = W_STOPCODE(info.si_status);
- break;
- case CLD_CONTINUED:
- // Set wait_status to a value that the caller can check via WIFCONTINUED.
- // glibc has a non-POSIX macro definition __W_CONTINUED for this value.
- *wait_status = 0xffff;
- break;
- default:
- *wait_status = 0;
- break;
- }
- }
-#else
-#error "wait4 and waitid syscalls not available."
-#endif
- if (pid < 0)
- return Error(-pid);
- return pid;
-}
-
-} // namespace internal
-} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_SYS_WAIT_WAIT4IMPL_H
More information about the libc-commits
mailing list