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 69 70 71 72 73 74 75 76 77
use std::{io, process, string};
/// Result type of this crate.
pub type Result<T> = std::result::Result<T, Error>;
/// Error raised when a process manager failed to kill hanged process after timeout. It is platform-specific.
#[cfg(unix)]
pub type KillError = nix::Error;
/// Error raised when a process manager failed to kill hanged process after timeout. It is platform-specific.
#[cfg(windows)]
pub type KillError = winapi::shared::minwindef::DWORD;
/// Error type of this crate.
#[derive(thiserror::Error, Debug)]
pub enum Error {
/// IO error that might happen during command / process execution.
#[error("IO error: {0}")]
IoError(io::Error),
/// Error raised when a process exits with a non-zero exit code.
#[error("Process exited with non-zero code: {:#?}. Output: {:#?}", .code, .output)]
NonZeroExitCode {
/// Exit code of a process. Might be absent on Unix systems when a process was terminated by a signal.
code: Option<i32>,
/// [`Output`](std::process::Output) of the exited process
output: process::Output,
},
/// Error raised when a child process does not return its identifier,
/// which means it does not exist at operating system level,
/// which is unexpected in the context of this program.
#[error("Process does not exist.")]
ProcessDoesNotExist,
/// When a process manager failed to kill hanged child process, there is a zombie process left hanging around.
/// This error provides details, such as process id and an error, so user could handle cleaning manually.
#[cfg(unix)]
#[error("Process with pid {pid} hanged and we were unable to kill it. Error: {err}", pid = .pid, err = .err)]
Zombie {
/// Process id of the hanged process.
pid: u32,
/// Error raised on attempt to terminate the hanged process.
err: KillError,
},
/// When a process manager failed to kill hanged child process, there is a zombie process left hanging around.
/// This error provides details, such as process id and an error, so user could handle cleaning manually.
#[cfg(windows)]
#[error("Process with pid {pid} hanged and we were unable to kill it. Error: {err}", pid = .pid, err = .err)]
Zombie {
/// Process id of the hanged process.
pid: u32,
/// Error raised on attempt to terminate the hanged process.
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,
}
}
}