use super::{ProcessControl, TreeReaper};
use std::io;
use std::sync::atomic::{AtomicI32, Ordering};
#[derive(Debug, Clone, Copy, Default)]
pub struct UnixProcessControl;
impl UnixProcessControl {
pub const fn new() -> Self {
Self
}
}
impl crate::sealed::Sealed for UnixProcessControl {}
impl ProcessControl for UnixProcessControl {
type Reaper = UnixReaper;
fn detach(&self, cmd: &mut tokio::process::Command) {
unsafe {
cmd.pre_exec(|| {
if libc::setsid() == -1 {
return Err(io::Error::last_os_error());
}
Ok(())
});
}
}
fn new_reaper(&self) -> io::Result<Self::Reaper> {
Ok(UnixReaper(AtomicI32::new(0)))
}
}
pub struct UnixReaper(AtomicI32);
impl TreeReaper for UnixReaper {
const ADOPTION_IS_ATOMIC: bool = true;
fn adopt(&self, child: &tokio::process::Child) -> io::Result<()> {
let Some(pid) = child.id() else {
return Err(io::Error::other("the child has already been reaped"));
};
self.0.store(pid as i32, Ordering::SeqCst);
Ok(())
}
fn kill_tree(&self) -> io::Result<()> {
let pid = self.0.load(Ordering::SeqCst);
if pid == 0 {
return Ok(()); }
unsafe {
libc::kill(-pid, libc::SIGKILL);
}
Ok(())
}
}