From 80db06d6daa290fbc722fbae6dbfa0728ca259b5 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 24 Sep 2019 21:34:44 -0700 Subject: [PATCH] Fix ExitStatus on Fuchsia Fuchsia exit codes don't follow the convention of libc::WEXITSTATUS et al, and they are 64 bits instead of 32 bits. This gives Fuchsia its own representation of ExitStatus. Additionally, the zircon syscall structs were out of date, causing us to see bogus return codes. --- src/libstd/sys/unix/process/mod.rs | 4 +- src/libstd/sys/unix/process/process_common.rs | 51 ------------------ .../sys/unix/process/process_fuchsia.rs | 38 ++++++++++++-- src/libstd/sys/unix/process/process_unix.rs | 52 +++++++++++++++++++ src/libstd/sys/unix/process/zircon.rs | 23 ++------ 5 files changed, 93 insertions(+), 75 deletions(-) diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs index 056a20345f404..553e980f08e97 100644 --- a/src/libstd/sys/unix/process/mod.rs +++ b/src/libstd/sys/unix/process/mod.rs @@ -1,5 +1,5 @@ -pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes}; -pub use self::process_inner::Process; +pub use self::process_common::{Command, ExitCode, Stdio, StdioPipes}; +pub use self::process_inner::{ExitStatus, Process}; pub use crate::ffi::OsString as EnvKey; mod process_common; diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 713d308555956..4edd2ebf8c598 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -393,57 +393,6 @@ impl fmt::Debug for Command { } } -/// Unix exit statuses -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -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) } - } - - pub fn success(&self) -> bool { - self.code() == Some(0) - } - - pub fn code(&self) -> Option { - if self.exited() { - Some(unsafe { libc::WEXITSTATUS(self.0) }) - } else { - None - } - } - - pub fn signal(&self) -> Option { - if !self.exited() { - Some(unsafe { libc::WTERMSIG(self.0) }) - } else { - None - } - } -} - -impl From for ExitStatus { - fn from(a: c_int) -> ExitStatus { - ExitStatus(a) - } -} - -impl fmt::Display for ExitStatus { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(code) = self.code() { - write!(f, "exit code: {}", code) - } else { - let signal = self.signal().unwrap(); - write!(f, "signal: {}", signal) - } - } -} - #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct ExitCode(u8); diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index fff9fc6b3bbc8..2b1a3ecfd70f5 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -1,11 +1,13 @@ +use crate::convert::TryInto; use crate::io; +use crate::fmt; use crate::mem; use crate::ptr; use crate::sys::process::zircon::{Handle, zx_handle_t}; use crate::sys::process::process_common::*; -use libc::size_t; +use libc::{c_int, size_t}; //////////////////////////////////////////////////////////////////////////////// // Command @@ -160,7 +162,7 @@ impl Process { return Err(io::Error::new(io::ErrorKind::InvalidData, "Failed to get exit status of process")); } - Ok(ExitStatus::new(proc_info.rec.return_code)) + Ok(ExitStatus(proc_info.return_code)) } pub fn try_wait(&mut self) -> io::Result> { @@ -190,6 +192,36 @@ impl Process { return Err(io::Error::new(io::ErrorKind::InvalidData, "Failed to get exit status of process")); } - Ok(Some(ExitStatus::new(proc_info.rec.return_code))) + Ok(Some(ExitStatus(proc_info.return_code))) + } +} + +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitStatus(i64); + +impl ExitStatus { + pub fn success(&self) -> bool { + self.code() == Some(0) + } + + pub fn code(&self) -> Option { + // FIXME: support extracting return code as an i64 + self.0.try_into().ok() + } + + pub fn signal(&self) -> Option { + None + } +} + +impl From for ExitStatus { + fn from(a: c_int) -> ExitStatus { + ExitStatus(a as i64) + } +} + +impl fmt::Display for ExitStatus { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "exit code: {}", self.0) } } diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index e6a742bd45d0b..507dc6892613a 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -1,3 +1,4 @@ +use crate::fmt; use crate::io::{self, Error, ErrorKind}; use crate::ptr; use crate::sys::cvt; @@ -441,3 +442,54 @@ impl Process { } } } + +/// Unix exit statuses +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +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) } + } + + pub fn success(&self) -> bool { + self.code() == Some(0) + } + + pub fn code(&self) -> Option { + if self.exited() { + Some(unsafe { libc::WEXITSTATUS(self.0) }) + } else { + None + } + } + + pub fn signal(&self) -> Option { + if !self.exited() { + Some(unsafe { libc::WTERMSIG(self.0) }) + } else { + None + } + } +} + +impl From for ExitStatus { + fn from(a: c_int) -> ExitStatus { + ExitStatus(a) + } +} + +impl fmt::Display for ExitStatus { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(code) = self.code() { + write!(f, "exit code: {}", code) + } else { + let signal = self.signal().unwrap(); + write!(f, "signal: {}", signal) + } + } +} diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index 1ba48de3c0785..188a6b5f2da4a 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -65,29 +65,14 @@ impl Drop for Handle { } } -// Common ZX_INFO header -#[derive(Default)] -#[repr(C)] -pub struct zx_info_header_t { - pub topic: u32, // identifies the info struct - pub avail_topic_size: u16, // “native” size of the struct - pub topic_size: u16, // size of the returned struct (<=topic_size) - pub avail_count: u32, // number of records the kernel has - pub count: u32, // number of records returned (limited by buffer size) -} - -#[derive(Default)] -#[repr(C)] -pub struct zx_record_process_t { - pub return_code: c_int, -} - // Returned for topic ZX_INFO_PROCESS #[derive(Default)] #[repr(C)] pub struct zx_info_process_t { - pub hdr: zx_info_header_t, - pub rec: zx_record_process_t, + pub return_code: i64, + pub started: bool, + pub exited: bool, + pub debugger_attached: bool, } extern {