use std::process::{Child, ExitStatus};
use super::ProcessError;
pub(crate) struct ChildGuard {
child: Child,
label: &'static str,
reaped: bool,
}
impl ChildGuard {
pub(crate) fn new(child: Child, label: &'static str) -> Self {
Self {
child,
label,
reaped: false,
}
}
pub(crate) fn try_wait(&mut self) -> Result<Option<ExitStatus>, ProcessError> {
let status = self.child.try_wait().map_err(|source| ProcessError::Wait {
program: self.label.to_owned(),
source,
})?;
if status.is_some() {
self.reaped = true;
}
Ok(status)
}
pub(crate) fn terminate(&mut self) -> Result<(), ProcessError> {
if self.try_wait()?.is_some() {
return Ok(());
}
self.child
.kill()
.map_err(|source| ProcessError::Terminate {
program: self.label,
source,
})?;
self.child.wait().map_err(|source| ProcessError::Wait {
program: self.label.to_owned(),
source,
})?;
self.reaped = true;
Ok(())
}
}
impl Drop for ChildGuard {
fn drop(&mut self) {
if !self.reaped {
let _ = self.child.kill();
let _ = self.child.wait();
}
}
}