Files
RedBear-OS/local/patches/relibc/absorbed/P3-waitid.patch
T
vasilito 5851974b20 feat: build system transition to release fork + archive hardening
Release fork infrastructure:
- REDBEAR_RELEASE=0.1.1 with offline enforcement (fetch/distclean/unfetch blocked)
- 195 BLAKE3-verified source archives in standard format
- Atomic provisioning via provision-release.sh (staging + .complete sentry)
- 5-phase improvement plan: restore format auto-detection, source tree
  validation (validate-source-trees.py), archive-map.json, REPO_BINARY fallback

Archive normalization:
- Removed 87 duplicate/unversioned archives from shared pool
- Regenerated all archives in consistent format with source/ + recipe.toml
- BLAKE3SUMS and manifest.json generated from stable tarball set

Patch management:
- verify-patches.sh: pre-sync dry-run report (OK/REVERSED/CONFLICT)
- 121 upstream-absorbed patches moved to absorbed/ directories
- 43 active patches verified clean against rebased sources
- Stress test: base updated to upstream HEAD, relibc reset and patched

Compilation fixes:
- relibc: Vec imports in redox-rt (proc.rs, lib.rs, sys.rs)
- relibc: unsafe from_raw_parts in mod.rs (2024 edition)
- fetch.rs: rev comparison handles short/full hash prefixes
- kibi recipe: corrected rev mismatch

New scripts: restore-sources.sh, provision-release.sh, verify-sources-archived.sh,
check-upstream-releases.sh, validate-source-trees.py, verify-patches.sh,
repair-archive-format.sh, generate-manifest.py

Documentation: AGENTS.md, README.md, local/AGENTS.md updated for release fork model
2026-05-02 01:41:17 +01:00

246 lines
6.0 KiB
Diff

diff --git a/src/header/sys_wait/mod.rs b/src/header/sys_wait/mod.rs
--- a/src/header/sys_wait/mod.rs
+++ b/src/header/sys_wait/mod.rs
@@ -4,12 +4,16 @@
use crate::{
error::ResultExt,
+ header::signal::siginfo_t,
out::Out,
platform::{
- Pal, Sys,
- types::{c_int, pid_t},
+ ERRNO, Pal, Sys,
+ types::{c_int, c_uint, pid_t},
},
};
+
+pub type idtype_t = c_int;
+pub type id_t = c_uint;
pub const WNOHANG: c_int = 1;
pub const WUNTRACED: c_int = 2;
@@ -24,25 +28,143 @@
#[allow(overflowing_literals)]
pub const __WCLONE: c_int = 0x8000_0000;
+pub const P_ALL: idtype_t = 0;
+pub const P_PID: idtype_t = 1;
+pub const P_PGID: idtype_t = 2;
+
+pub const CLD_EXITED: c_int = 1;
+pub const CLD_KILLED: c_int = 2;
+pub const CLD_DUMPED: c_int = 3;
+pub const CLD_TRAPPED: c_int = 4;
+pub const CLD_STOPPED: c_int = 5;
+pub const CLD_CONTINUED: c_int = 6;
+
+fn wexitstatus(status: c_int) -> c_int {
+ (status >> 8) & 0xff
+}
+
+fn wtermsig(status: c_int) -> c_int {
+ status & 0x7f
+}
+
+fn wstopsig(status: c_int) -> c_int {
+ wexitstatus(status)
+}
+
+fn wcoredump(status: c_int) -> bool {
+ (status & 0x80) != 0
+}
+
+fn wifexited(status: c_int) -> bool {
+ (status & 0x7f) == 0
+}
+
+fn wifstopped(status: c_int) -> bool {
+ (status & 0xff) == 0x7f
+}
+
+fn wifcontinued(status: c_int) -> bool {
+ status == 0xffff
+}
+
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn wait(stat_loc: *mut c_int) -> pid_t {
unsafe { waitpid(!0, stat_loc, 0) }
}
-/*
- * TODO: implement idtype_t, id_t, and siginfo_t
- *
- * #[unsafe(no_mangle)]
- * pub unsafe extern "C" fn waitid(
- * idtype: idtype_t,
- * id: id_t,
- * infop: siginfo_t,
- * options: c_int
- * ) -> c_int {
- * unimplemented!();
- * }
- */
+fn map_waitid_target(idtype: idtype_t, id: id_t) -> Option<pid_t> {
+ match idtype {
+ P_ALL => Some(-1),
+ P_PID => Some(id as pid_t),
+ P_PGID => Some(if id == 0 { 0 } else { -(id as pid_t) }),
+ _ => None,
+ }
+}
+
+fn map_waitid_options(options: c_int) -> Option<c_int> {
+ let interest = options & (WEXITED | WSTOPPED | WCONTINUED);
+ if interest == 0 {
+ return None;
+ }
+
+ let mut waitpid_options = 0;
+ if options & WNOHANG != 0 {
+ waitpid_options |= WNOHANG;
+ }
+ if options & WSTOPPED != 0 {
+ waitpid_options |= WUNTRACED;
+ }
+ if options & WCONTINUED != 0 {
+ waitpid_options |= WCONTINUED;
+ }
+ if options & WNOWAIT != 0 {
+ waitpid_options |= WNOWAIT;
+ }
+
+ Some(waitpid_options)
+}
+
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn waitid(
+ idtype: idtype_t,
+ id: id_t,
+ infop: *mut siginfo_t,
+ options: c_int,
+) -> c_int {
+ if infop.is_null() {
+ ERRNO.set(crate::header::errno::EFAULT);
+ return -1;
+ }
+
+ let Some(pid_target) = map_waitid_target(idtype, id) else {
+ ERRNO.set(crate::header::errno::EINVAL);
+ return -1;
+ };
+ let Some(waitpid_options) = map_waitid_options(options) else {
+ ERRNO.set(crate::header::errno::EINVAL);
+ return -1;
+ };
+
+ let mut status = 0;
+ let pid = Sys::waitpid(pid_target, Some(Out::from_mut(&mut status)), waitpid_options)
+ .or_minus_one_errno();
+ if pid < 0 {
+ return -1;
+ }
+
+ unsafe {
+ *infop = core::mem::zeroed();
+ }
+ if pid == 0 {
+ return 0;
+ }
+
+ unsafe {
+ (*infop).si_pid = pid;
+ (*infop).si_signo = crate::header::signal::SIGCHLD as c_int;
+ (*infop).si_errno = 0;
+ if wifexited(status) {
+ (*infop).si_code = CLD_EXITED;
+ (*infop).si_status = wexitstatus(status);
+ } else if wifstopped(status) {
+ (*infop).si_code = CLD_STOPPED;
+ (*infop).si_status = wstopsig(status);
+ } else if wifcontinued(status) {
+ (*infop).si_code = CLD_CONTINUED;
+ (*infop).si_status = crate::header::signal::SIGCONT as c_int;
+ } else {
+ (*infop).si_status = wtermsig(status);
+ (*infop).si_code = if wcoredump(status) {
+ CLD_DUMPED
+ } else {
+ CLD_KILLED
+ };
+ }
+ }
+
+ 0
+}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/waitpid.html>.
#[unsafe(no_mangle)]
diff --git a/tests/Makefile.tests.mk b/tests/Makefile.tests.mk
--- a/tests/Makefile.tests.mk
+++ b/tests/Makefile.tests.mk
@@ -312,6 +312,7 @@
grp/getgrgid_r \
grp/getgrnam_r \
grp/gr_iter \
+ waitid \
waitpid \
waitpid_multiple \
$(FAILING_TESTS)
diff --git a/tests/waitid.c b/tests/waitid.c
new file mode 100644
--- /dev/null
+++ b/tests/waitid.c
@@ -0,0 +1,50 @@
+#include <assert.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "test_helpers.h"
+
+static void wait_until_child_exits(pid_t pid) {
+ siginfo_t info;
+ for (int i = 0; i < 50; ++i) {
+ info.si_pid = 0;
+ int ret = waitid(P_PID, pid, &info, WEXITED | WNOHANG | WNOWAIT);
+ ERROR_IF(waitid, ret, == -1);
+ if (info.si_pid == pid) {
+ assert(info.si_code == CLD_EXITED);
+ assert(info.si_status == 42);
+ return;
+ }
+ usleep(10000);
+ }
+ assert(!"waitid never observed child exit");
+}
+
+int main(void) {
+ pid_t pid = fork();
+ ERROR_IF(fork, pid, == -1);
+
+ if (pid == 0) {
+ usleep(50000);
+ _Exit(42);
+ }
+
+ siginfo_t info;
+ info.si_pid = 0;
+ int ret = waitid(P_PID, pid, &info, WEXITED | WNOHANG | WNOWAIT);
+ ERROR_IF(waitid, ret, == -1);
+ assert(info.si_pid == 0);
+
+ wait_until_child_exits(pid);
+
+ int status = 0;
+ pid_t waited = waitpid(pid, &status, 0);
+ ERROR_IF(waitpid, waited, == -1);
+ assert(waited == pid);
+ assert(WIFEXITED(status));
+ assert(WEXITSTATUS(status) == 42);
+
+ return EXIT_SUCCESS;
+}