process: sys_wait4: return ECHILD with no children

If the calling process has no children and no pending exit events to
handle, return ECHILD instead of waiting forever.
This commit is contained in:
Matthew Leach
2026-01-11 22:20:45 +00:00
committed by Ashwin Naren
parent a003ab8f71
commit 64bc004cdb
3 changed files with 12 additions and 2 deletions

View File

@@ -177,6 +177,9 @@ pub enum KernelError {
#[error("No such process")]
NoProcess,
#[error("No child process")]
NoChildProcess,
#[error("Operation timed out")]
TimedOut,

View File

@@ -53,6 +53,7 @@ pub fn kern_err_to_syscall(err: KernelError) -> isize {
KernelError::NotSupported => ENOSYS,
KernelError::NoMemory => ENOMEM,
KernelError::TimedOut => ETIMEDOUT,
KernelError::NoChildProcess => ECHILD,
e => todo!("{e}"),
}
}

View File

@@ -170,7 +170,12 @@ pub async fn sys_wait4(
let task = current_task_shared();
let (tgid, child_state) = if flags.contains(WaitFlags::WNOHANG) {
let child_proc_count = task.process.children.lock_save_irq().iter().count();
let (tgid, child_state) = if child_proc_count == 0 || flags.contains(WaitFlags::WNOHANG) {
// Special case for no children. See if there are any pending child
// notification events without sleeping. If there are no children and no
// pending events, return ECHILD.
let mut ret = None;
task.process.child_notifiers.inner.update(|s| {
ret = do_wait(s, pid, flags);
@@ -178,8 +183,9 @@ pub async fn sys_wait4(
});
match ret {
None => return Ok(0),
Some(ret) => ret,
None if child_proc_count == 0 => return Err(KernelError::NoChildProcess),
None => return Ok(0),
}
} else {
task.process