about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-11-11 18:11:17 -0800
committerbors <bors@rust-lang.org>2013-11-11 18:11:17 -0800
commit86787f8befe0f8971f27bd15be1e16ec7aa99e7e (patch)
tree481ca094a98776594c0810dfc5b4767d8e9fae9a /src/libstd/rt
parentc0b7972f7d63e4b55098797cb48949b00d3ffee7 (diff)
parentf698decf3701cc51a61bbc3e36971898339ba91e (diff)
downloadrust-86787f8befe0f8971f27bd15be1e16ec7aa99e7e.tar.gz
rust-86787f8befe0f8971f27bd15be1e16ec7aa99e7e.zip
auto merge of #10109 : pcmattman/rust/pass-nonzero-exit-status-on-termination-by-signal, r=alexcrichton
The UvProcess exit callback is called with a zero exit status and non-zero termination signal when a child is terminated by a signal.

If a parent checks only the exit status (for example, only checks the return value from `wait()`), it may believe the process completed successfully when it actually failed.

Helpers for common use-cases are in `std::rt::io::process`.

Should resolve https://github.com/mozilla/rust/issues/10062.
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/io/process.rs38
-rw-r--r--src/libstd/rt/rtio.rs4
2 files changed, 39 insertions, 3 deletions
diff --git a/src/libstd/rt/io/process.rs b/src/libstd/rt/io/process.rs
index ae087099d1f..6b21cde2488 100644
--- a/src/libstd/rt/io/process.rs
+++ b/src/libstd/rt/io/process.rs
@@ -18,6 +18,8 @@ use rt::io;
 use rt::io::io_error;
 use rt::rtio::{RtioProcess, IoFactory, with_local_io};
 
+use fmt;
+
 // windows values don't matter as long as they're at least one of unix's
 // TERM/KILL/INT signals
 #[cfg(windows)] pub static PleaseExitSignal: int = 15;
@@ -79,6 +81,40 @@ pub enum StdioContainer {
     CreatePipe(bool /* readable */, bool /* writable */),
 }
 
+/// Describes the result of a process after it has terminated.
+#[deriving(Eq)]
+pub enum ProcessExit {
+    /// Normal termination with an exit status.
+    ExitStatus(int),
+
+    /// Termination by signal, with the signal number.
+    ExitSignal(int),
+}
+
+impl fmt::Default for ProcessExit {
+    /// Format a ProcessExit enum, to nicely present the information.
+    fn fmt(obj: &ProcessExit, f: &mut fmt::Formatter) {
+        match *obj {
+            ExitStatus(code) =>  write!(f.buf, "exit code: {}", code),
+            ExitSignal(code) =>  write!(f.buf, "signal: {}", code),
+        }
+    }
+}
+
+impl ProcessExit {
+    /// Was termination successful? Signal termination not considered a success,
+    /// and success is defined as a zero exit status.
+    pub fn success(&self) -> bool {
+        return self.matches_exit_status(0);
+    }
+
+    /// Checks whether this ProcessExit matches the given exit status.
+    /// Termination by signal will never match an exit code.
+    pub fn matches_exit_status(&self, wanted: int) -> bool {
+        *self == ExitStatus(wanted)
+    }
+}
+
 impl Process {
     /// Creates a new pipe initialized, but not bound to any particular
     /// source/destination
@@ -122,7 +158,7 @@ impl Process {
     /// Wait for the child to exit completely, returning the status that it
     /// exited with. This function will continue to have the same return value
     /// after it has been called at least once.
-    pub fn wait(&mut self) -> int { self.handle.wait() }
+    pub fn wait(&mut self) -> ProcessExit { self.handle.wait() }
 }
 
 impl Drop for Process {
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
index d623914cdad..9b1103b8a74 100644
--- a/src/libstd/rt/rtio.rs
+++ b/src/libstd/rt/rtio.rs
@@ -18,7 +18,7 @@ use c_str::CString;
 use ai = rt::io::net::addrinfo;
 use rt::io::IoError;
 use rt::io::signal::Signum;
-use super::io::process::ProcessConfig;
+use super::io::process::{ProcessConfig, ProcessExit};
 use super::io::net::ip::{IpAddr, SocketAddr};
 use path::Path;
 use super::io::{SeekStyle};
@@ -201,7 +201,7 @@ pub trait RtioFileStream {
 pub trait RtioProcess {
     fn id(&self) -> libc::pid_t;
     fn kill(&mut self, signal: int) -> Result<(), IoError>;
-    fn wait(&mut self) -> int;
+    fn wait(&mut self) -> ProcessExit;
 }
 
 pub trait RtioPipe {