1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
use std::{
convert::TryInto,
io::{Error, Result},
process::Child,
};
use nix::{
sys::signal::{kill, Signal},
unistd::Pid,
};
/// Unix-specific extensions to process [`Child`]ren.
pub trait UnixChildExt {
/// Sends a signal to the child process. If the process has already exited, an [`InvalidInput`]
/// error is returned.
///
/// # Examples
///
/// Basic usage:
///
/// ```no_run
/// use std::process::Command;
/// use command_group::{UnixChildExt, Signal};
///
/// let mut command = Command::new("yes");
/// if let Ok(mut child) = command.spawn() {
/// child.signal(Signal::SIGTERM).expect("command wasn't running");
/// } else {
/// println!("yes command didn't start");
/// }
/// ```
///
/// With a process group:
///
/// ```no_run
/// use std::process::Command;
/// use command_group::{CommandGroup, UnixChildExt, Signal};
///
/// let mut command = Command::new("yes");
/// if let Ok(mut child) = command.group_spawn() {
/// child.signal(Signal::SIGTERM).expect("command wasn't running");
/// } else {
/// println!("yes command didn't start");
/// }
/// ```
///
/// [`InvalidInput`]: std::io::ErrorKind::InvalidInput
fn signal(&self, sig: Signal) -> Result<()>;
}
impl UnixChildExt for Child {
fn signal(&self, sig: Signal) -> Result<()> {
let pid = Pid::from_raw(self.id().try_into().expect("Command PID > i32::MAX"));
kill(pid, sig).map_err(Error::from)
}
}
#[cfg(feature = "with-tokio")]
impl UnixChildExt for ::tokio::process::Child {
fn signal(&self, sig: Signal) -> Result<()> {
if let Some(id) = self.id() {
let pid = Pid::from_raw(id.try_into().expect("Command PID > i32::MAX"));
kill(pid, sig).map_err(Error::from)
} else {
Ok(())
}
}
}