Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add os.wait3 and os.wait4 with EINTR retry
Assisted-by: Grok:4.6
  • Loading branch information
youknowone committed Sep 17, 2026
commit ba7503f0b90dffaa89ecc1f6f8ded3c0a53e46a8
41 changes: 41 additions & 0 deletions crates/host_env/src/posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,47 @@ pub fn waitpid(pid: libc::pid_t, status: &mut i32, opt: i32) -> std::io::Result<
}
}

unsafe extern "C" {
#[link_name = "wait4"]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
fn libc_wait4(
pid: libc::pid_t,
status: *mut libc::c_int,
options: libc::c_int,
rusage: *mut libc::rusage,
) -> libc::pid_t;
}

/// `wait3(2)` is `wait4(-1, ...)`.
pub fn wait3(options: i32) -> std::io::Result<(libc::pid_t, i32, crate::resource::RUsage)> {
wait4_rusage(-1, options)
}

/// `wait4(2)`. `rusage` is zeroed when `pid == 0` (WNOHANG, no child ready).
pub fn wait4(
pid: libc::pid_t,
options: i32,
) -> std::io::Result<(libc::pid_t, i32, crate::resource::RUsage)> {
wait4_rusage(pid, options)
}

fn wait4_rusage(
pid: libc::pid_t,
options: i32,
) -> std::io::Result<(libc::pid_t, i32, crate::resource::RUsage)> {
let mut status = 0;
let mut ru = core::mem::MaybeUninit::<libc::rusage>::zeroed();
let res = unsafe { libc_wait4(pid, &mut status, options, ru.as_mut_ptr()) };
if res == -1 {
return Err(std::io::Error::last_os_error());
}
let ru = if res == 0 {
unsafe { core::mem::zeroed() }
} else {
unsafe { ru.assume_init() }
};
Ok((res, status, ru.into()))
}

pub fn kill(pid: i32, sig: i32) -> std::io::Result<()> {
let ret = unsafe { libc::kill(pid, sig) };
if ret == -1 {
Expand Down
59 changes: 59 additions & 0 deletions crates/vm/src/stdlib/posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,65 @@ pub mod module {
waitpid(-1, 0, vm)
}

fn rusage_to_py(
ru: rustpython_host_env::resource::RUsage,
vm: &VirtualMachine,
) -> PyResult<PyObjectRef> {
let resource = vm.import("resource", 0)?;
let struct_rusage = resource.get_attr("struct_rusage", vm)?;
let tv = |t: rustpython_host_env::resource::timeval| {
t.tv_sec as f64 + (t.tv_usec as f64 / 1_000_000.0)
};
let fields = vm.ctx.new_tuple(vec![
vm.ctx.new_float(tv(ru.ru_utime)).into(),
vm.ctx.new_float(tv(ru.ru_stime)).into(),
vm.ctx.new_int(ru.ru_maxrss).into(),
vm.ctx.new_int(ru.ru_ixrss).into(),
vm.ctx.new_int(ru.ru_idrss).into(),
vm.ctx.new_int(ru.ru_isrss).into(),
vm.ctx.new_int(ru.ru_minflt).into(),
vm.ctx.new_int(ru.ru_majflt).into(),
vm.ctx.new_int(ru.ru_nswap).into(),
vm.ctx.new_int(ru.ru_inblock).into(),
vm.ctx.new_int(ru.ru_oublock).into(),
vm.ctx.new_int(ru.ru_msgsnd).into(),
vm.ctx.new_int(ru.ru_msgrcv).into(),
vm.ctx.new_int(ru.ru_nsignals).into(),
vm.ctx.new_int(ru.ru_nvcsw).into(),
vm.ctx.new_int(ru.ru_nivcsw).into(),
]);
struct_rusage.call((fields,), vm)
}

fn wait_with_rusage<F>(vm: &VirtualMachine, wait: F) -> PyResult<PyTupleRef>
where
F: Fn() -> std::io::Result<(libc::pid_t, i32, rustpython_host_env::resource::RUsage)>,
{
loop {
match vm.allow_threads(|| wait()) {
Err(err) if err.raw_os_error() == Some(libc::EINTR) => {
vm.check_signals()?;
continue;
}
Err(err) => return Err(err.into_pyexception(vm)),
Ok((pid, status, ru)) => {
let rusage = rusage_to_py(ru, vm)?;
return Ok(vm.new_tuple((pid, status, rusage)));
}
}
}
}

#[pyfunction]
fn wait3(options: i32, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
wait_with_rusage(vm, || rustpython_host_env::posix::wait3(options))
}

#[pyfunction]
fn wait4(pid: libc::pid_t, options: i32, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
wait_with_rusage(vm, || rustpython_host_env::posix::wait4(pid, options))
}

#[pyfunction]
fn kill(pid: i32, signal: isize, vm: &VirtualMachine) -> PyResult<()> {
rustpython_host_env::posix::kill(pid, signal as i32).map_err(|err| err.into_pyexception(vm))
Expand Down
Loading