Skip to content

Commit

Permalink
Add a way to wait on process by PID
Browse files Browse the repository at this point in the history
This is needed to make processes work in `async-process`.

Signed-off-by: John Nunley <[email protected]>
  • Loading branch information
notgull committed Jan 16, 2024
1 parent 6125508 commit 41885d9
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 11 deletions.
9 changes: 3 additions & 6 deletions examples/wait-signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
35 changes: 30 additions & 5 deletions src/os/kqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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.
Expand All @@ -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,
}
}
}

Expand All @@ -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,
Expand All @@ -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) })
}
}

Expand Down

0 comments on commit 41885d9

Please sign in to comment.