2024-01-03 03:22:36 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2025-12-04 05:57:54 +00:00
|
|
|
use ostd::mm::VmIo;
|
|
|
|
|
|
2024-05-03 20:36:19 +00:00
|
|
|
use super::SyscallReturn;
|
2024-02-25 14:09:24 +00:00
|
|
|
use crate::{
|
|
|
|
|
prelude::*,
|
2025-07-21 10:37:48 +00:00
|
|
|
process::{
|
|
|
|
|
do_wait,
|
|
|
|
|
signal::{
|
|
|
|
|
c_types::siginfo_t,
|
|
|
|
|
constants::{CLD_CONTINUED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, SIGCHLD, SIGCONT},
|
|
|
|
|
},
|
|
|
|
|
ProcessFilter, WaitOptions, WaitStatus,
|
|
|
|
|
},
|
2024-02-25 14:09:24 +00:00
|
|
|
};
|
2022-11-04 06:22:28 +00:00
|
|
|
|
2022-09-27 11:51:18 +00:00
|
|
|
pub fn sys_waitid(
|
|
|
|
|
which: u64,
|
|
|
|
|
upid: u64,
|
2025-07-21 10:37:48 +00:00
|
|
|
infoq_addr: u64,
|
2022-09-27 11:51:18 +00:00
|
|
|
options: u64,
|
2024-08-11 12:17:25 +00:00
|
|
|
_rusage_addr: u64,
|
2024-09-14 02:12:31 +00:00
|
|
|
ctx: &Context,
|
2022-11-04 06:22:28 +00:00
|
|
|
) -> Result<SyscallReturn> {
|
2025-07-21 10:37:48 +00:00
|
|
|
// FIXME: what does rusage use for?
|
2025-06-05 07:25:07 +00:00
|
|
|
let process_filter = ProcessFilter::from_which_and_id(which, upid as _, ctx)?;
|
2024-08-21 12:56:03 +00:00
|
|
|
let wait_options = WaitOptions::from_bits(options as u32)
|
|
|
|
|
.ok_or(Error::with_message(Errno::EINVAL, "invalid options"))?;
|
2025-05-01 15:51:37 +00:00
|
|
|
|
2025-07-21 10:37:48 +00:00
|
|
|
// Check for waitid options
|
|
|
|
|
if !wait_options
|
|
|
|
|
.intersects(WaitOptions::WSTOPPED | WaitOptions::WCONTINUED | WaitOptions::WEXITED)
|
|
|
|
|
{
|
|
|
|
|
return_errno_with_message!(
|
|
|
|
|
Errno::EINVAL,
|
|
|
|
|
"at least one of WSTOPPED, WCONTINUED, or WEXITED should be specified"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-12 03:11:16 +00:00
|
|
|
let wait_status =
|
|
|
|
|
do_wait(process_filter, wait_options, ctx).map_err(|err| match err.error() {
|
2024-12-16 03:32:37 +00:00
|
|
|
Errno::EINTR => Error::new(Errno::ERESTARTSYS),
|
|
|
|
|
_ => err,
|
|
|
|
|
})?;
|
2025-05-01 15:51:37 +00:00
|
|
|
|
2025-07-21 10:37:48 +00:00
|
|
|
let Some(wait_status) = wait_status else {
|
|
|
|
|
return Ok(SyscallReturn::Return(0));
|
|
|
|
|
};
|
|
|
|
|
|
2025-06-05 07:25:07 +00:00
|
|
|
if infoq_addr != 0 {
|
|
|
|
|
let siginfo = {
|
|
|
|
|
let (si_code, si_status) = calculate_si_code_and_si_status(&wait_status);
|
|
|
|
|
let pid = wait_status.pid();
|
|
|
|
|
let uid = wait_status.uid();
|
2025-07-21 10:37:48 +00:00
|
|
|
|
2025-06-05 07:25:07 +00:00
|
|
|
let mut siginfo = siginfo_t::new(SIGCHLD, si_code);
|
|
|
|
|
siginfo.set_pid_uid(pid, uid);
|
|
|
|
|
siginfo.set_status(si_status);
|
2025-07-21 10:37:48 +00:00
|
|
|
|
2025-06-05 07:25:07 +00:00
|
|
|
siginfo
|
|
|
|
|
};
|
2025-07-21 10:37:48 +00:00
|
|
|
|
2025-06-05 07:25:07 +00:00
|
|
|
ctx.user_space().write_val(infoq_addr as usize, &siginfo)?;
|
|
|
|
|
}
|
2025-07-21 10:37:48 +00:00
|
|
|
|
|
|
|
|
Ok(SyscallReturn::Return(0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn calculate_si_code_and_si_status(wait_status: &WaitStatus) -> (i32, i32) {
|
|
|
|
|
// TODO: Add supports for `CLD_DUMPED` and `CLD_TRAPPED`.
|
|
|
|
|
match wait_status {
|
|
|
|
|
WaitStatus::Zombie(process) => {
|
|
|
|
|
const NORMAL_EXIT_MASK: u32 = 0xff;
|
|
|
|
|
|
|
|
|
|
let exit_code = process.status().exit_code();
|
|
|
|
|
// If the process exits normally, the lowest 8 bits of `status_code`
|
|
|
|
|
// will be zero. In this case, we return the actual exit code by
|
|
|
|
|
// shifting the `status_code` right by 8 bits.
|
|
|
|
|
if (exit_code & NORMAL_EXIT_MASK) == 0 {
|
|
|
|
|
(CLD_EXITED, (exit_code >> 8) as i32)
|
|
|
|
|
} else {
|
|
|
|
|
(CLD_KILLED, exit_code as i32)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
WaitStatus::Stop(_process, signum) => (CLD_STOPPED, signum.as_u8() as i32),
|
|
|
|
|
WaitStatus::Continue(_) => (CLD_CONTINUED, SIGCONT.as_u8() as i32),
|
|
|
|
|
}
|
2022-09-27 11:51:18 +00:00
|
|
|
}
|