diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 3eee45d000cd1..2dedb2df08a2a 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1489,6 +1489,40 @@ impl Child {
let status = self.wait()?;
Ok(Output { status, stdout, stderr })
}
+
+ /// Indicates that the process has exited and the exit status is known.
+ ///
+ /// You should only call this function after using `waitpid` on Unix or an
+ /// equivalent function on another platform. It will cause future calls to
+ /// [`wait`] and [`wait_with_output`] to use this exit status.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::process::{Child, ExitStatus};
+ /// use std::process::{Command, Stdio};
+ ///
+ /// let mut child = Command::new("echo")
+ /// .arg("Hello world")
+ /// .stdout(Stdio::piped())
+ /// .spawn()
+ /// .expect("failed to execute child");
+ ///
+ /// # fn external_wait(child: &mut Child) -> ExitStatus {
+ /// # child.wait().unwrap()
+ /// # }
+ /// let status = external_wait(&mut child);
+ /// child.set_status(status);
+ ///
+ /// assert_eq!(status, child.wait().expect("failed to wait on child"));
+ /// ```
+ ///
+ /// [`wait`]: #method.wait
+ /// [`wait_with_output`]: #method.wait_with_output
+ #[stable(feature = "child_set_status", since = "1.44.0")]
+ pub fn set_status(&mut self, status: ExitStatus) {
+ self.handle.set_status(status.0);
+ }
}
/// Terminates the current process with the specified exit code.
diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs
index 4702e5c549228..48467b881cfd5 100644
--- a/src/libstd/sys/cloudabi/shims/process.rs
+++ b/src/libstd/sys/cloudabi/shims/process.rs
@@ -146,4 +146,6 @@ impl Process {
pub fn try_wait(&mut self) -> io::Result> {
match self.0 {}
}
+
+ pub fn set_status(&mut self, _: ExitStatus) {}
}
diff --git a/src/libstd/sys/hermit/process.rs b/src/libstd/sys/hermit/process.rs
index 4702e5c549228..48467b881cfd5 100644
--- a/src/libstd/sys/hermit/process.rs
+++ b/src/libstd/sys/hermit/process.rs
@@ -146,4 +146,6 @@ impl Process {
pub fn try_wait(&mut self) -> io::Result > {
match self.0 {}
}
+
+ pub fn set_status(&mut self, _: ExitStatus) {}
}
diff --git a/src/libstd/sys/sgx/process.rs b/src/libstd/sys/sgx/process.rs
index 4702e5c549228..48467b881cfd5 100644
--- a/src/libstd/sys/sgx/process.rs
+++ b/src/libstd/sys/sgx/process.rs
@@ -146,4 +146,6 @@ impl Process {
pub fn try_wait(&mut self) -> io::Result > {
match self.0 {}
}
+
+ pub fn set_status(&mut self, _: ExitStatus) {}
}
diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs
index f0bd1cdfed52f..794e3e78fc43d 100644
--- a/src/libstd/sys/unix/process/process_fuchsia.rs
+++ b/src/libstd/sys/unix/process/process_fuchsia.rs
@@ -32,7 +32,7 @@ impl Command {
let process_handle = unsafe { self.do_exec(theirs, envp.as_ref())? };
- Ok((Process { handle: Handle::new(process_handle) }, ours))
+ Ok((Process { handle: Handle::new(process_handle), status: None }, ours))
}
pub fn exec(&mut self, default: Stdio) -> io::Error {
@@ -139,6 +139,7 @@ impl Command {
pub struct Process {
handle: Handle,
+ status: Option,
}
impl Process {
@@ -160,6 +161,10 @@ impl Process {
use crate::default::Default;
use crate::sys::process::zircon::*;
+ if let Some(status) = self.status {
+ return Ok(status);
+ }
+
let mut proc_info: zx_info_process_t = Default::default();
let mut actual: size_t = 0;
let mut avail: size_t = 0;
@@ -186,13 +191,19 @@ impl Process {
"Failed to get exit status of process",
));
}
- Ok(ExitStatus(proc_info.return_code))
+ let status = ExitStatus(proc_info.return_code);
+ self.set_status(status);
+ Ok(status)
}
pub fn try_wait(&mut self) -> io::Result> {
use crate::default::Default;
use crate::sys::process::zircon::*;
+ if let Some(status) = self.status {
+ return Ok(status);
+ }
+
let mut proc_info: zx_info_process_t = Default::default();
let mut actual: size_t = 0;
let mut avail: size_t = 0;
@@ -224,7 +235,12 @@ impl Process {
"Failed to get exit status of process",
));
}
- Ok(Some(ExitStatus(proc_info.return_code)))
+ self.set_status(ExitStatus(proc_info.return_code));
+ Ok(self.status)
+ }
+
+ pub fn set_status(&mut self, status: ExitStatus) {
+ self.status = Some(status);
}
}
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 07d0fbf61fe22..91ef14d91138f 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -436,8 +436,8 @@ impl Process {
}
let mut status = 0 as c_int;
cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
- self.status = Some(ExitStatus::new(status));
- Ok(ExitStatus::new(status))
+ self.set_status(ExitStatus(status));
+ Ok(ExitStatus(status))
}
pub fn try_wait(&mut self) -> io::Result > {
@@ -446,12 +446,14 @@ impl Process {
}
let mut status = 0 as c_int;
let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?;
- if pid == 0 {
- Ok(None)
- } else {
- self.status = Some(ExitStatus::new(status));
- Ok(Some(ExitStatus::new(status)))
+ if pid != 0 {
+ self.set_status(ExitStatus(status));
}
+ Ok(self.status)
+ }
+
+ pub fn set_status(&mut self, status: ExitStatus) {
+ self.status = Some(status);
}
}
@@ -460,10 +462,6 @@ impl Process {
pub struct ExitStatus(c_int);
impl ExitStatus {
- pub fn new(status: c_int) -> ExitStatus {
- ExitStatus(status)
- }
-
fn exited(&self) -> bool {
unsafe { libc::WIFEXITED(self.0) }
}
diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs
index 6d5506bec5f7d..37b846309273a 100644
--- a/src/libstd/sys/vxworks/process/process_common.rs
+++ b/src/libstd/sys/vxworks/process/process_common.rs
@@ -344,10 +344,6 @@ impl fmt::Debug for Command {
pub struct ExitStatus(c_int);
impl ExitStatus {
- pub fn new(status: c_int) -> ExitStatus {
- ExitStatus(status)
- }
-
fn exited(&self) -> bool {
/*unsafe*/
{ libc::WIFEXITED(self.0) }
diff --git a/src/libstd/sys/vxworks/process/process_vxworks.rs b/src/libstd/sys/vxworks/process/process_vxworks.rs
index f7e84ae3de9c7..55b76f0976461 100644
--- a/src/libstd/sys/vxworks/process/process_vxworks.rs
+++ b/src/libstd/sys/vxworks/process/process_vxworks.rs
@@ -149,8 +149,8 @@ impl Process {
}
let mut status = 0 as c_int;
cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
- self.status = Some(ExitStatus::new(status));
- Ok(ExitStatus::new(status))
+ self.set_status(ExitStatus(status));
+ Ok(ExitStatus(status))
}
pub fn try_wait(&mut self) -> io::Result > {
@@ -159,11 +159,13 @@ impl Process {
}
let mut status = 0 as c_int;
let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?;
- if pid == 0 {
- Ok(None)
- } else {
- self.status = Some(ExitStatus::new(status));
- Ok(Some(ExitStatus::new(status)))
+ if pid != 0 {
+ self.set_status(ExitStatus(status));
}
+ Ok(self.status)
+ }
+
+ pub fn set_status(&mut self, status: ExitStatus) {
+ self.status = Some(status);
}
}
diff --git a/src/libstd/sys/wasi/process.rs b/src/libstd/sys/wasi/process.rs
index 7156c9ab92f2b..4cbfae0b624ed 100644
--- a/src/libstd/sys/wasi/process.rs
+++ b/src/libstd/sys/wasi/process.rs
@@ -146,4 +146,6 @@ impl Process {
pub fn try_wait(&mut self) -> io::Result > {
match self.0 {}
}
+
+ pub fn set_status(&mut self, _: ExitStatus) {}
}
diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs
index 4702e5c549228..48467b881cfd5 100644
--- a/src/libstd/sys/wasm/process.rs
+++ b/src/libstd/sys/wasm/process.rs
@@ -146,4 +146,6 @@ impl Process {
pub fn try_wait(&mut self) -> io::Result > {
match self.0 {}
}
+
+ pub fn set_status(&mut self, _: ExitStatus) {}
}
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index a62a637393ea3..82aca0a8df79b 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -220,7 +220,7 @@ impl Command {
// around to be able to close it later.
drop(Handle::new(pi.hThread));
- Ok((Process { handle: Handle::new(pi.hProcess) }, pipes))
+ Ok((Process { handle: Handle::new(pi.hProcess), status: None }, pipes))
}
}
@@ -319,6 +319,7 @@ impl From for Stdio {
/// for the process to terminate.
pub struct Process {
handle: Handle,
+ status: Option,
}
impl Process {
@@ -332,6 +333,9 @@ impl Process {
}
pub fn wait(&mut self) -> io::Result {
+ if let Some(status) = self.status {
+ return Ok(status);
+ }
unsafe {
let res = c::WaitForSingleObject(self.handle.raw(), c::INFINITE);
if res != c::WAIT_OBJECT_0 {
@@ -339,11 +343,15 @@ impl Process {
}
let mut status = 0;
cvt(c::GetExitCodeProcess(self.handle.raw(), &mut status))?;
+ self.set_status(ExitStatus(status));
Ok(ExitStatus(status))
}
}
pub fn try_wait(&mut self) -> io::Result> {
+ if let Some(status) = self.status {
+ return Ok(Some(status));
+ }
unsafe {
match c::WaitForSingleObject(self.handle.raw(), 0) {
c::WAIT_OBJECT_0 => {}
@@ -354,10 +362,15 @@ impl Process {
}
let mut status = 0;
cvt(c::GetExitCodeProcess(self.handle.raw(), &mut status))?;
- Ok(Some(ExitStatus(status)))
+ self.set_status(ExitStatus(status));
+ Ok(self.status)
}
}
+ pub fn set_status(&mut self, status: ExitStatus) {
+ self.status = Some(status);
+ }
+
pub fn handle(&self) -> &Handle {
&self.handle
}