From 41885d96b3b9436de88fca8ca255bf45e0c2d08a Mon Sep 17 00:00:00 2001 From: John Nunley Date: Mon, 15 Jan 2024 17:35:08 -0800 Subject: [PATCH] Add a way to wait on process by PID This is needed to make processes work in `async-process`. Signed-off-by: John Nunley --- examples/wait-signal.rs | 9 +++------ src/os/kqueue.rs | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/examples/wait-signal.rs b/examples/wait-signal.rs index d4f5bc3..a7afd07 100644 --- a/examples/wait-signal.rs +++ b/examples/wait-signal.rs @@ -33,12 +33,9 @@ mod example { // Process events. for ev in events.iter() { - match ev.key { - 1 => { - println!("SIGINT received"); - return; - } - _ => unreachable!(), + if ev.key == 1 { + println!("SIGINT received"); + return; } } diff --git a/src/os/kqueue.rs b/src/os/kqueue.rs index aae36c3..888c735 100644 --- a/src/os/kqueue.rs +++ b/src/os/kqueue.rs @@ -4,6 +4,7 @@ use crate::sys::{mode_to_flags, SourceId}; use crate::{PollMode, Poller}; use std::io; +use std::marker::PhantomData; use std::process::Child; use std::time::Duration; @@ -171,11 +172,14 @@ impl Filter for Signal {} /// Monitor a child process. #[derive(Debug)] pub struct Process<'a> { - /// The child process to monitor. - child: &'a Child, + /// The process ID to monitor. + pid: std::os::raw::c_int, /// The operation to monitor. ops: ProcessOps, + + /// Lifetime of the underlying process. + _lt: PhantomData<&'a Child>, } /// The operations that a monitored process can perform. @@ -200,7 +204,26 @@ impl<'a> Process<'a> { /// Once registered into the `Poller`, the `Child` object must outlive this filter's /// registration into the poller. pub unsafe fn new(child: &'a Child, ops: ProcessOps) -> Self { - Self { child, ops } + Self { + pid: rustix::process::Pid::from_child(child) + .as_raw_nonzero() + .get(), + ops, + _lt: PhantomData, + } + } + + /// Create a `Process` from a PID. + /// + /// # Safety + /// + /// The PID must be tied to an actual child process. + pub unsafe fn from_pid(pid: std::num::NonZeroI32, ops: ProcessOps) -> Self { + Self { + pid: pid.get(), + ops, + _lt: PhantomData, + } } } @@ -215,7 +238,8 @@ unsafe impl FilterSealed for Process<'_> { kqueue::Event::new( kqueue::EventFilter::Proc { - pid: rustix::process::Pid::from_child(self.child), + // SAFETY: We know that the PID is nonzero. + pid: unsafe { rustix::process::Pid::from_raw_unchecked(self.pid) }, flags: events, }, flags | kqueue::EventFlags::RECEIPT, @@ -225,7 +249,8 @@ unsafe impl FilterSealed for Process<'_> { #[inline(always)] fn source_id(&self) -> SourceId { - SourceId::Pid(rustix::process::Pid::from_child(self.child)) + // SAFETY: We know that the PID is nonzero + SourceId::Pid(unsafe { rustix::process::Pid::from_raw_unchecked(self.pid) }) } }