Files
RedBear-OS/local/patches/relibc/P3-waitid.patch
T
vasilito ba360adfbc Consolidate relibc overlay patch chain
Keep the relibc compatibility work in tracked local patch carriers and align the recipe with the full durable patch stack so clean reapply and rebuild paths stay reproducible.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-18 21:36:07 +01:00

151 lines
4.2 KiB
Diff

diff --git a/src/header/sys_wait/mod.rs b/src/header/sys_wait/mod.rs
index 11f4bf2c..23e1a356 100644
--- a/src/header/sys_wait/mod.rs
+++ b/src/header/sys_wait/mod.rs
@@ -4,13 +4,17 @@
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,112 @@ pub const __WALL: c_int = 0x4000_0000;
#[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;
+ }
+ 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)]