mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Add os.wait3 and os.wait4 with EINTR retry (#8728)
* Add os.wait3 and os.wait4 with EINTR retry Assisted-by: Grok:4.6 * Unskip multiprocessing Finalize thread-safety test Assisted-by: Grok:4.6 * Fix wait4 clippy lint and use libc wait4 Assisted-by: Grok:4.6
This commit is contained in:
1 parent
ce470e3928
commit
982cbd4d25
3 files changed
+83
-1
No files matched your search
Vendored
-1
@@ -5009,7 +5009,6 @@ class _TestFinalize(BaseTestCase):
|
||||
result = [obj for obj in iter(conn.recv, 'STOP')]
|
||||
self.assertEqual(result, ['a', 'b', 'd10', 'd03', 'd02', 'd01', 'e'])
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON; SIGSEGV due to dict thread-safety issue under aggressive GC")
|
||||
@support.requires_resource('cpu')
|
||||
def test_thread_safety(self):
|
||||
# bpo-24484: _run_finalizers() should be thread-safe
|
||||
|
||||
@@ -971,6 +971,30 @@ pub fn waitpid(pid: libc::pid_t, status: &mut i32, opt: i32) -> std::io::Result<
|
||||
}
|
||||
}
|
||||
|
||||
/// `wait3(2)` is `wait4(-1, ...)`.
|
||||
pub fn wait3(options: i32) -> std::io::Result<(libc::pid_t, i32, crate::resource::RUsage)> {
|
||||
wait4(-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)> {
|
||||
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 {
|
||||
|
||||
@@ -1824,6 +1824,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))
|
||||
|
||||
Reference in new issue
Block a user