use std::{io, process, string};
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(unix)]
pub type KillError = nix::Error;
#[cfg(windows)]
pub type KillError = winapi::shared::minwindef::DWORD;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("IO error: {0}")]
IoError(io::Error),
#[error("Interrupted.")]
Interrupted,
#[error("Killed [pid: {pid}].")]
Killed {
pid: u32,
},
#[error("Process exited with non-zero code: {code:?}. Output: {output:#?}")]
NonZeroExitCode {
code: Option<i32>,
output: process::Output,
},
#[error("Process does not exist.")]
ProcessDoesNotExist,
#[cfg(unix)]
#[error("Process with pid {pid} hanged and we were unable to kill it. Error: {err}")]
Zombie {
pid: u32,
err: KillError,
},
#[cfg(windows)]
#[error("Process with pid {pid} hanged and we were unable to kill it. Error: {err}")]
Zombie {
pid: u32,
err: KillError,
},
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Self::IoError(err)
}
}
impl From<string::FromUtf8Error> for Error {
fn from(err: string::FromUtf8Error) -> Self {
Self::IoError(io::Error::new(io::ErrorKind::InvalidInput, err))
}
}
impl From<process::Output> for Error {
fn from(output: process::Output) -> Self {
if output.status.success() {
panic!("Failed to convert command output to error because the command succeeded. Output: {:#?}", output);
}
Self::NonZeroExitCode {
code: output.status.code(),
output,
}
}
}