summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock26
-rw-r--r--Cargo.toml1
-rw-r--r--src/backends/clang.rs48
-rw-r--r--src/backends/mod.rs10
-rw-r--r--src/backends/python.rs18
-rw-r--r--src/conf.rs19
6 files changed, 98 insertions, 24 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fd8da7f..4e1c095 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -31,6 +31,11 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "cc"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -69,6 +74,7 @@ dependencies = [
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -107,6 +113,18 @@ version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "nix"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
+ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "proc-macro2"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -221,6 +239,11 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "wait-timeout"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -269,6 +292,7 @@ dependencies = [
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
@@ -277,6 +301,7 @@ dependencies = [
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
+"checksum nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd0eaf8df8bab402257e0a5c17a254e4cc1f72a93588a1ddfb5d356c801aa7cb"
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
@@ -293,6 +318,7 @@ dependencies = [
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum wait-timeout 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b9f3bf741a801531993db6478b95682117471f76916f5e690dd8d45395b09349"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
diff --git a/Cargo.toml b/Cargo.toml
index 937517b..183516f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,3 +14,4 @@ log = "0.4"
env_logger = "0.7.1"
wait-timeout = "0.1.5"
lazy_static = "1.4.0"
+nix = "0.16"
diff --git a/src/backends/clang.rs b/src/backends/clang.rs
index a174af6..b732ed5 100644
--- a/src/backends/clang.rs
+++ b/src/backends/clang.rs
@@ -1,4 +1,5 @@
use serde_derive::{ Serialize, Deserialize };
+use crate::backends::{ Backend, mk_tmp_dir, RunStatus };
use std::path::{ Path, PathBuf };
use std::io::{ Result, Error, ErrorKind };
use std::process::Command;
@@ -6,7 +7,6 @@ use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use log::trace;
-type Result<T> = std::io::Result<T>;
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ClangBackend {
@@ -75,14 +75,46 @@ impl Backend for ClangBackend {
}
}
- fn run(&self, fname: &Path) -> std::io::Result<()> {
+ fn run(&self, fname: &Path) -> Result<RunStatus> {
let binary_fname = self.build(fname)?;
- Command::new(&binary_fname)
- .status()
- .map(|status| {
- trace!("{:#?}", status);
- ()
- })
+ let binary_proc = Command::new(&binary_fname).spawn()?;
+ get_status(binary_proc)
}
}
+
+use nix::sys::wait;
+
+#[cfg(unix)]
+fn get_status(proc: std::process::Child) -> Result<RunStatus> {
+ let id = proc.id() as i32; // for fuck sake, why this emits u32?
+
+ loop {
+ let status_result = wait::waitpid(Some(nix::unistd::Pid::from_raw(id)), None)
+ .map_err(|err| Error::new(ErrorKind::Other, err));
+
+ let status = status_result?;
+ match status {
+ wait::WaitStatus::Exited(pid, code) => {
+ assert_eq!(pid.as_raw(), id);
+
+ if code == 0 {
+ return Ok(RunStatus::Success);
+ } else {
+ return Ok(RunStatus::ErrorCode(code));
+ }
+ },
+ wait::WaitStatus::Signaled(pid, sig, coredump) => {
+ assert_eq!(pid.as_raw(), id);
+
+ return Ok(RunStatus::Signal(sig, coredump));
+ }
+ _ => continue,
+ }
+ }
+}
+
+#[cfg(not(unix))]
+fn get_status(proc: std::process::Child) -> Result<RunStatus> {
+ compile_error!("currently only unix supported");
+} \ No newline at end of file
diff --git a/src/backends/mod.rs b/src/backends/mod.rs
index b91bde5..25ac164 100644
--- a/src/backends/mod.rs
+++ b/src/backends/mod.rs
@@ -2,6 +2,7 @@ use std::path::{ Path, PathBuf };
use std::env::temp_dir;
use lazy_static::lazy_static;
use std::io::{ Error, ErrorKind, Result };
+use nix::sys::signal::Signal as NixSignal;
pub mod python;
pub mod clang;
@@ -13,10 +14,17 @@ lazy_static! {
static ref EVR_TMP_DIR: PathBuf = temp_dir().join("evr-tmp");
}
+pub enum RunStatus {
+ Success,
+ ErrorCode(i32),
+ TimedOut(std::time::Duration),
+ Signal(NixSignal, bool),
+}
+
pub trait Backend {
fn get_template(&self) -> Option<&str>;
- fn run(&self, fname: &Path) -> Result<()>;
+ fn run(&self, fname: &Path) -> Result<RunStatus>;
fn try_guess_test_file(&self, fname: &Path) -> Option<PathBuf> {
let maybe_test = fname.with_extension("txt");
diff --git a/src/backends/python.rs b/src/backends/python.rs
index 39827a7..2398997 100644
--- a/src/backends/python.rs
+++ b/src/backends/python.rs
@@ -1,10 +1,9 @@
use serde_derive::{ Serialize, Deserialize };
-use crate::backends::Backend;
+use crate::backends::{ Backend, RunStatus };
use std::process::{ Command, Stdio };
use std::path::Path;
-use std::io::{ Error, ErrorKind };
use std::fs::File;
-use log::{ trace, warn, error };
+use log::{ warn, error };
use wait_timeout::ChildExt;
#[derive(Debug, Serialize, Deserialize, Default)]
@@ -35,7 +34,7 @@ impl Backend for PythonBackend {
}
}
- fn run(&self, fname: &Path) -> std::io::Result<()> {
+ fn run(&self, fname: &Path) -> std::io::Result<RunStatus> {
let stdio = match self.try_guess_test_file(fname) {
Some(test_filename) => match File::open(test_filename) {
Ok(test_content) => Stdio::from(test_content),
@@ -58,19 +57,16 @@ impl Backend for PythonBackend {
match child.wait_timeout(timeout) {
Ok(maybe_status) => match maybe_status {
Some(status) => {
- trace!("elapsed: {:#?}", timer.elapsed());
if !status.success() {
- return Err(Error::new(ErrorKind::Other,
- "process exited with non-zero exit code"));
+ return Ok(RunStatus::ErrorCode(status.code().unwrap_or(0)));
}
- Ok(())
+ Ok(RunStatus::Success)
},
None => {
- warn!("timed out: {:#?}", timer.elapsed());
+ let elapsed = timer.elapsed().unwrap_or(Default::default());
child.kill()?;
child.wait()?;
- Err(Error::new(ErrorKind::TimedOut,
- "process timed out"))
+ Ok(RunStatus::TimedOut(elapsed))
}
},
Err(err) => {
diff --git a/src/conf.rs b/src/conf.rs
index e36a932..dec461f 100644
--- a/src/conf.rs
+++ b/src/conf.rs
@@ -7,7 +7,7 @@ use std::io::prelude::*;
type Error = std::io::Error;
use std::io::ErrorKind;
-use crate::backends::{ Backend, PythonBackend, ClangBackend };
+use crate::backends::{ Backend, PythonBackend, ClangBackend, RunStatus };
#[derive(Debug, Serialize, Deserialize, Default)]
@@ -43,9 +43,20 @@ impl Conf {
}
pub fn run(&self, fname: &Path) -> std::io::Result<()> {
- self.get_backend(fname)
- .and_then(|backend| Some(backend.run(fname)))
- .unwrap_or(Err(Error::new(ErrorKind::InvalidData, "Backend not found")))
+ match self.get_backend(fname) {
+ Some(backend) => backend.run(fname).map(|status| {
+ match status {
+ RunStatus::Success => {},
+ RunStatus::ErrorCode(code) =>
+ { error!("process exited with code: {}", code); },
+ RunStatus::TimedOut(duration) =>
+ { error!("process timed out at {:.3}s", duration.as_secs_f32()); }
+ RunStatus::Signal(sig, coredump) =>
+ { error!("process killed by {} {}", sig, if coredump { "(core dumped)" } else { "" }); }
+ };
+ }),
+ None => Err(Error::new(ErrorKind::InvalidData, "Backend not found"))
+ }
}
pub fn make(&self, fname: &Path) -> std::io::Result<()> {