Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
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
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ exclude = ["/.*"]

[dependencies]
async-lock = "3.0.0"
async-io = "2.3.0"
async-io = "2.4.0"
cfg-if = "1.0"
event-listener = "5.1.0"
futures-lite = "2.0.0"
Expand All @@ -26,7 +26,7 @@ tracing = { version = "0.1.40", default-features = false, optional = true }
async-signal = "0.2.3"
rustix = { version = "1.0", default-features = false, features = ["std", "fs", "process"] }

[target.'cfg(any(windows, target_os = "linux"))'.dependencies]
[target.'cfg(any(windows, target_os = "linux", target_os = "freebsd"))'.dependencies]
async-channel = "2.0.0"
async-task = "4.7.0"

Expand Down
10 changes: 5 additions & 5 deletions src/reaper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
#![allow(irrefutable_let_patterns)]

/// Enable the waiting reaper.
#[cfg(any(windows, target_os = "linux"))]
#[cfg(any(windows, target_os = "linux", target_os = "freebsd"))]
macro_rules! cfg_wait {
($($tt:tt)*) => {$($tt)*};
}

/// Enable the waiting reaper.
#[cfg(not(any(windows, target_os = "linux")))]
#[cfg(not(any(windows, target_os = "linux", target_os = "freebsd")))]
macro_rules! cfg_wait {
($($tt:tt)*) => {};
}
Expand Down Expand Up @@ -48,7 +48,7 @@ use std::sync::Mutex;

/// The underlying system reaper.
pub(crate) enum Reaper {
#[cfg(any(windows, target_os = "linux"))]
#[cfg(any(windows, target_os = "linux", target_os = "freebsd"))]
/// The reaper based on the wait backend.
Wait(wait::Reaper),

Expand All @@ -59,7 +59,7 @@ pub(crate) enum Reaper {

/// The wrapper around a child.
pub(crate) enum ChildGuard {
#[cfg(any(windows, target_os = "linux"))]
#[cfg(any(windows, target_os = "linux", target_os = "freebsd"))]
/// The child guard based on the wait backend.
Wait(wait::ChildGuard),

Expand All @@ -70,7 +70,7 @@ pub(crate) enum ChildGuard {

/// A lock on the reaper.
pub(crate) enum Lock {
#[cfg(any(windows, target_os = "linux"))]
#[cfg(any(windows, target_os = "linux", target_os = "freebsd"))]
/// The wait-based reaper needs no lock.
Wait,

Expand Down
48 changes: 48 additions & 0 deletions src/reaper/wait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,54 @@ cfg_if::cfg_if! {
}
}

/// Tell if we are able to use this backend.
pub(crate) fn available() -> bool {
true
}
} else if #[cfg(target_os = "freebsd")] {
use async_io::os::kqueue::{Exit, Filter};
use std::num::NonZeroI32;

/// Waitable version of `std::process::Child`
struct WaitableChild {
child: std::process::Child,
handle: Filter<Exit>,
}

impl WaitableChild {
fn new(child: std::process::Child) -> io::Result<Self> {
// std::process::Child id must provide a positive PID value
let exit_filter = unsafe {
Filter::new(Exit::from_pid(NonZeroI32::new_unchecked(
child
.id()
.try_into()
.expect("could not transform pid to i32 type"),
)))?
};

Ok(Self {
handle: exit_filter,
child: child,
})
}

fn get_mut(&mut self) -> &mut std::process::Child {
&mut self.child
}

fn poll_wait(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<std::process::ExitStatus>> {
loop {
if let Some(status) = self.child.try_wait()? {
return Poll::Ready(Ok(status));
}

// Wait for us to become readable.
futures_lite::ready!(self.handle.poll_ready(cx))?;
}
}
}

/// Tell if we are able to use this backend.
pub(crate) fn available() -> bool {
true
Expand Down
Loading