summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsyn <isaqtm@gmail.com>2020-02-14 13:09:44 +0300
committersyn <isaqtm@gmail.com>2020-02-14 13:09:44 +0300
commit3da19e8603c00c02ec7e24ea8910a7c386b09018 (patch)
treebb9740afd63099a6038c22b82cf84cba8c9218e9 /src
parent30e1e3a13dc19c47afc517d1178e1dbf5b401596 (diff)
downloadevr-3da19e8603c00c02ec7e24ea8910a7c386b09018.tar.gz
Improve error handling
Diffstat (limited to 'src')
-rw-r--r--src/backends/clang.rs4
-rw-r--r--src/backends/mod.rs4
-rw-r--r--src/backends/python.rs4
-rw-r--r--src/conf.rs51
-rw-r--r--src/main.rs38
-rw-r--r--src/wait/error.rs26
-rw-r--r--src/wait/mod.rs31
7 files changed, 83 insertions, 75 deletions
diff --git a/src/backends/clang.rs b/src/backends/clang.rs
index 0947b49..11c316a 100644
--- a/src/backends/clang.rs
+++ b/src/backends/clang.rs
@@ -5,7 +5,7 @@ use std::io::{ Result as IoResult, Error, ErrorKind };
use std::process::{ Command };
use std::collections::hash_map::DefaultHasher;
use std::hash::{ Hash, Hasher };
-use crate::wait::{ WaitInfo, wait_child };
+use crate::wait::{ ChildExitStatus, wait_child };
use std::time::Duration;
@@ -81,7 +81,7 @@ impl Backend for ClangBackend {
}
}
- fn run(&self, fname: &Path) -> Result<WaitInfo, RunError> {
+ fn run(&self, fname: &Path) -> Result<ChildExitStatus, RunError> {
let binary_fname = self.build(fname)?;
let proc = Command::new(&binary_fname)
diff --git a/src/backends/mod.rs b/src/backends/mod.rs
index 3bf9fc7..a5d2d28 100644
--- a/src/backends/mod.rs
+++ b/src/backends/mod.rs
@@ -2,7 +2,7 @@ use std::path::{ Path, PathBuf };
use std::env::temp_dir;
use lazy_static::lazy_static;
use std::io::{ Error, ErrorKind };
-use crate::wait::{ WaitInfo };
+use crate::wait::ChildExitStatus;
pub mod python;
pub mod clang;
@@ -21,7 +21,7 @@ lazy_static! {
pub trait Backend {
fn get_template(&self) -> Option<&str>;
- fn run(&self, fname: &Path) -> Result<WaitInfo, RunError>;
+ fn run(&self, fname: &Path) -> Result<ChildExitStatus, RunError>;
}
fn mk_tmp_dir() -> std::io::Result<&'static std::path::PathBuf> {
diff --git a/src/backends/python.rs b/src/backends/python.rs
index e3569b1..3ee7b35 100644
--- a/src/backends/python.rs
+++ b/src/backends/python.rs
@@ -2,7 +2,7 @@ use serde_derive::{ Serialize, Deserialize };
use crate::backends::{ Backend, RunError };
use std::process::{ Command };
use std::path::Path;
-use crate::wait::{ wait_child, WaitInfo };
+use crate::wait::{ wait_child, ChildExitStatus };
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct PythonBackend {
@@ -32,7 +32,7 @@ impl Backend for PythonBackend {
}
}
- fn run(&self, fname: &Path) -> Result<WaitInfo, RunError> {
+ fn run(&self, fname: &Path) -> Result<ChildExitStatus, RunError> {
let timer = std::time::Instant::now();
let child = Command::new(self.get_interpreter())
diff --git a/src/conf.rs b/src/conf.rs
index febfef5..cc281f0 100644
--- a/src/conf.rs
+++ b/src/conf.rs
@@ -1,14 +1,12 @@
use serde_derive::{ Serialize, Deserialize };
use std::path::{ PathBuf, Path };
use toml::de;
-use log::{ error, trace };
-use std::io::prelude::*;
-use nix::sys::wait::WaitStatus;
+use log::{ error };
type Error = std::io::Error;
use std::io::ErrorKind;
-use crate::backends::{ Backend, PythonBackend, ClangBackend, RunError };
+use crate::backends::{ Backend, PythonBackend, ClangBackend };
#[derive(Debug, Serialize, Deserialize, Default)]
@@ -42,51 +40,6 @@ impl Conf {
_ => None
}
}
-
- pub fn run(
- &self,
- fname: &Path,
- show_time: bool,
- show_mem: bool
- ) -> Result<(), RunError> {
- match self.get_backend(fname) {
- Some(backend) => backend.run(fname).map(|info| {
- match info.status {
- WaitStatus::Exited(_pid, ret) => match ret {
- 0 => {
- if show_time {
- println!("wall time: {:?}", info.wall_time);
- }
- if show_mem {
- println!("rss: {}K", info.usage.ru_maxrss);
- }
- },
- _ => error!("process exited with {}", ret)
- },
- WaitStatus::Signaled(pid, sig, coredump) => {
- error!(
- "process killed by {} {}. was {}",
- sig,
- if coredump {"(core dumped)"} else {""},
- pid
- );
- },
- _ => error!("process signaled, but not exited")
- }
- }),
- None => Err(Error::new(ErrorKind::InvalidData, "Backend not found").into())
- }
- }
-
- pub fn make(&self, fname: &Path) -> Result<(), RunError> {
- trace!("Template: {:?}", self.get_template(&fname));
-
- std::fs::File::create(fname)?
- .write_all(self.get_template(fname).as_bytes())?;
-
- trace!("Written some bytes to {}", fname.to_string_lossy());
- Ok(())
- }
}
diff --git a/src/main.rs b/src/main.rs
index 1621e1b..4eeb298 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,6 +3,7 @@ extern crate lazy_static;
use clap::{ AppSettings, App, Arg };
use env_logger;
use log::{ error };
+use std::io::prelude::*;
mod conf;
mod backends;
@@ -41,19 +42,28 @@ fn main() {
.into();
let config = conf::get_conf();
- let result =
- if src_path.exists() {
- config.run(
- &src_path,
- matches.is_present("time"),
- matches.is_present("mem")
- )
+ if src_path.exists() {
+ if let Some(backend) = config.get_backend(&src_path) {
+ match backend.run(&src_path) {
+ Ok(status) => {
+ if matches.is_present("time") {
+ println!("wall time: {:?}", status.wall_time);
+ }
+ if matches.is_present("mem") {
+ println!("rss: {}K", status.usage.ru_maxrss);
+ }
+ },
+ Err(err) => error!("{}", err)
+ };
} else {
- config.make(&src_path)
- };
-
- match result {
- Ok(_) => {},
- Err(err) => error!("{}", err)
- }
+ error!("could not match backend");
+ }
+ } else {
+ let template = config.get_template(&src_path).as_bytes();
+ if let Err(err) =
+ std::fs::File::create(&src_path)
+ .and_then(|mut file| file.write_all(template)) {
+ error!("{}", err);
+ }
+ };
}
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);