diff options
author | syn <isaqtm@gmail.com> | 2020-02-14 13:09:44 +0300 |
---|---|---|
committer | syn <isaqtm@gmail.com> | 2020-02-14 13:09:44 +0300 |
commit | 3da19e8603c00c02ec7e24ea8910a7c386b09018 (patch) | |
tree | bb9740afd63099a6038c22b82cf84cba8c9218e9 /src/wait | |
parent | 30e1e3a13dc19c47afc517d1178e1dbf5b401596 (diff) | |
download | evr-3da19e8603c00c02ec7e24ea8910a7c386b09018.tar.gz |
Improve error handling
Diffstat (limited to 'src/wait')
-rw-r--r-- | src/wait/error.rs | 26 | ||||
-rw-r--r-- | src/wait/mod.rs | 31 |
2 files changed, 51 insertions, 6 deletions
diff --git a/src/wait/error.rs b/src/wait/error.rs index bb95e81..169097d 100644 --- a/src/wait/error.rs +++ b/src/wait/error.rs @@ -2,11 +2,22 @@ use nix; use std::time::Duration; #[derive(Debug)] +pub struct ProcessSignalInfo { + pub pid: nix::unistd::Pid, + pub signal: nix::sys::signal::Signal, + pub coredump: bool +} + +#[derive(Debug)] pub enum WaitError { TimedOut(Duration), - OsError(nix::Error) + ReturnNonZero(i32, nix::unistd::Pid), + Signaled(ProcessSignalInfo), + OsError(nix::Error), + NotExited } + impl From<nix::Error> for WaitError { fn from(err: nix::Error) -> Self { WaitError::OsError(err) @@ -17,7 +28,13 @@ impl std::fmt::Display for WaitError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match *self { WaitError::TimedOut(dur) => write!(f, "process timed out in {:?}", dur), - WaitError::OsError(err) => err.fmt(f) + WaitError::ReturnNonZero(ret, pid) => + write!(f, "process exited with non-zero exit code ({}). was {}", ret, pid), + WaitError::Signaled(ref info) => + write!(f, "process killed by {} {}. was {}", + info.signal, if info.coredump {"(core dumped)"} else {""}, info.pid), + WaitError::OsError(err) => err.fmt(f), + WaitError::NotExited => write!(f, "process signaled, but not exited") } } } @@ -25,7 +42,10 @@ impl std::fmt::Display for WaitError { impl std::error::Error for WaitError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match *self { - WaitError::TimedOut(_) => None, + WaitError::TimedOut(_) | + WaitError::ReturnNonZero(_, _) | + WaitError::Signaled(_) | + WaitError::NotExited => None, WaitError::OsError(ref e) => Some(e) } } diff --git a/src/wait/mod.rs b/src/wait/mod.rs index 9761f08..c591bb1 100644 --- a/src/wait/mod.rs +++ b/src/wait/mod.rs @@ -8,20 +8,45 @@ use std::time::{ Instant, Duration }; use std::process::Child; use std::thread; use std::sync::mpsc; +use std::convert::{ TryFrom, TryInto }; mod error; mod rusage_ffi; pub use rusage_ffi::Rusage; pub use error::WaitError; +use error::ProcessSignalInfo; #[derive(Debug)] -pub struct WaitInfo { +struct WaitInfo { pub status: WaitStatus, pub usage: Rusage, pub wall_time: Duration } +#[derive(Debug)] +pub struct ChildExitStatus { + pub usage: Rusage, + pub wall_time: Duration +} + +impl TryFrom<WaitInfo> for ChildExitStatus { + type Error = WaitError; + + fn try_from(info: WaitInfo) -> Result<Self, Self::Error> { + match info.status { + WaitStatus::Exited(pid, ret) => + match ret { + 0 => Ok(ChildExitStatus { usage: info.usage, wall_time: info.wall_time }), + _ => Err(WaitError::ReturnNonZero(ret, pid)) + }, + WaitStatus::Signaled(pid, signal, coredump) => + Err(WaitError::Signaled(ProcessSignalInfo { pid, signal, coredump })), + _ => Err(WaitError::NotExited) + } + } +} + fn wait4_pid( pid: Pid, @@ -57,14 +82,14 @@ pub fn wait_child( mut child: Child, timeout: Duration, timer: Instant -) -> Result<WaitInfo, WaitError> { +) -> Result<ChildExitStatus, WaitError> { let pid = Pid::from_raw(child.id() as i32); let (send, recv) = mpsc::channel(); let thr = thread::spawn(move || wait4_pid(pid, send, timer)); match recv.recv_timeout(timeout) { - Ok(Ok(usg)) => Ok(usg), + Ok(Ok(wait_info)) => wait_info.try_into(), Ok(Err(err)) => Err(err.into()), Err(mpsc::RecvTimeoutError::Timeout) => { drop(recv); |