diff options
| author | Jonas Maier <> | 2026-03-11 12:30:07 +0100 |
|---|---|---|
| committer | Jonas Maier <> | 2026-03-11 12:30:07 +0100 |
| commit | 15501132916dfbc24f23b619e6d5408f258fc0d9 (patch) | |
| tree | a77e27bfc139415baf7faf09eeaefec360db9423 /src/wait/child.rs | |
| parent | b881eec59118bc630b64378476f4d5ada2bf5968 (diff) | |
| download | pish-15501132916dfbc24f23b619e6d5408f258fc0d9.tar.gz | |
can wait for threads & processes with a timeout now
Diffstat (limited to 'src/wait/child.rs')
| -rw-r--r-- | src/wait/child.rs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/wait/child.rs b/src/wait/child.rs new file mode 100644 index 0000000..29a7d70 --- /dev/null +++ b/src/wait/child.rs @@ -0,0 +1,81 @@ +//! based on https://www.man7.org/linux/man-pages/man2/pidfd_open.2.html +#![cfg(target_os = "linux")] + +use std::{ + io, + mem::ManuallyDrop, + ops::{Deref, DerefMut}, + os::fd::{BorrowedFd, RawFd}, + process::{Child, ExitStatus}, + ptr, +}; + +use libc::{SYS_pidfd_open, syscall}; +use nix::poll::{PollFd, PollFlags}; + +pub struct ChildWaiter { + fd: RawFd, + child: Child, +} + +#[derive(Debug)] +struct PidFdOpenError; + +impl std::fmt::Display for PidFdOpenError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "pid_fd_open") + } +} + +impl std::error::Error for PidFdOpenError {} + +impl ChildWaiter { + pub fn new(child: Child) -> io::Result<Self> { + let fd = unsafe { syscall(SYS_pidfd_open, child.id(), 0) }; + if fd < 0 { + Err(io::Error::new(io::ErrorKind::Other, PidFdOpenError)) + } else { + let fd = fd as RawFd; + Ok(Self { child, fd }) + } + } + + pub fn wait(&mut self, timeout_ms: u16) -> io::Result<Option<ExitStatus>> { + let mut poll_fds = [PollFd::new( + unsafe { BorrowedFd::borrow_raw(self.fd) }, + PollFlags::POLLIN, + )]; + let _ = nix::poll::poll(&mut poll_fds, timeout_ms); + self.child.try_wait() + } + + pub fn into_inner(self) -> Child { + unsafe { + libc::close(self.fd); + } + let this = ManuallyDrop::new(self); + unsafe { ptr::read(&this.child) } + } +} + +impl Deref for ChildWaiter { + type Target = Child; + + fn deref(&self) -> &Self::Target { + &self.child + } +} + +impl DerefMut for ChildWaiter { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.child + } +} + +impl Drop for ChildWaiter { + fn drop(&mut self) { + unsafe { + libc::close(self.fd); + } + } +} |
