Skip to content

Commit

Permalink
Add ExitStatusExt::aborted_code for Fuchsia platform
Browse files Browse the repository at this point in the history
  • Loading branch information
c6c7 committed Jul 11, 2024
1 parent 848c591 commit ba47433
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 14 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,8 @@ declare_features! (
(unstable, fn_align, "1.53.0", Some(82232)),
/// Support delegating implementation of functions to other already implemented functions.
(incomplete, fn_delegation, "1.76.0", Some(118212)),
/// Support ExitStatusExt::aborted_code on Fuchsia platform.
(unstable, fuchsia_exit_status_aborted, "1.79.0", None),
/// Allows impls for the Freeze trait.
(internal, freeze_impls, "1.78.0", Some(121675)),
/// Allows defining gen blocks and `gen fn`.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,7 @@ symbols! {
fs_create_dir,
fsub_algebraic,
fsub_fast,
fuchsia_exit_status_aborted,
fundamental,
fused_iterator,
future,
Expand Down
2 changes: 2 additions & 0 deletions library/std/src/os/fuchsia/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
#![stable(feature = "raw_ext", since = "1.1.0")]

pub mod fs;
#[unstable(feature = "fuchsia_exit_status_aborted", issue = "none")]
pub mod process;
pub mod raw;
25 changes: 25 additions & 0 deletions library/std/src/os/fuchsia/process.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! Fuchsia-specific extensions to primitives in the [`std::process`] module.
//!
//! [`std::process`]: crate::process

use crate::process;
use crate::sealed::Sealed;

#[unstable(feature = "fuchsia_exit_status_aborted", issue = "none")]
pub trait ExitStatusExt: Sealed {
/// If the process was aborted, returns the status code.
#[must_use]
fn aborted_code(&self) -> Option<i32>;
}

#[unstable(feature = "fuchsia_exit_status_aborted", issue = "none")]
impl ExitStatusExt for process::ExitStatus {
/// If the process was aborted, returns the status code.
fn aborted_code(&self) -> Option<i32> {
match self.code() {
// Upon an abort, Fuchsia returns the status code ZX_TASK_RETCODE_EXCEPTION_KILL.
code @ Some(-1028) => code,
Some(_) | None => None,
}
}
}
1 change: 1 addition & 0 deletions library/test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#![feature(process_exitcode_internals)]
#![feature(panic_can_unwind)]
#![feature(test)]
#![cfg_attr(target_os = "fuchsia", feature(fuchsia_exit_status_aborted))]
#![allow(internal_features)]

// Public reexports
Expand Down
28 changes: 15 additions & 13 deletions library/test/src/test_result.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::any::Any;
use std::process::ExitStatus;

#[cfg(target_os = "fuchsia")]
use std::os::fuchsia::process::ExitStatusExt as _;
#[cfg(unix)]
use std::os::unix::process::ExitStatusExt;
use std::os::unix::process::ExitStatusExt as _;

use super::bench::BenchSamples;
use super::options::ShouldPanic;
Expand Down Expand Up @@ -88,30 +90,30 @@ pub fn get_result_from_exit_code(
time_opts: &Option<time::TestTimeOptions>,
exec_time: &Option<time::TestExecTime>,
) -> TestResult {
let result = match status.code() {
#[cfg(target_os = "fuchsia")]
let result = status.aborted_code().map(|_| TestResult::TrFailed);
#[cfg(not(target_os = "fuchsia"))]
let result: Option<TestResult> = None;

let result = result.unwrap_or_else(|| match status.code() {
Some(TR_OK) => TestResult::TrOk,
// On Windows we use __fastfail to abort, which is documented to use this
// exception code.
#[cfg(windows)]
Some(0xC0000409u32 as i32) => TestResult::TrFailed,
#[cfg(unix)]
#[cfg(any(windows, unix))]
Some(code) => TestResult::TrFailedMsg(format!("got unexpected return code {code}")),
#[cfg(not(any(windows, unix)))]
Some(_) => TestResult::TrFailed,
None => match status.signal() {
#[cfg(unix)]
Some(libc::SIGABRT) => TestResult::TrFailed,
Some(signal) => {
TestResult::TrFailedMsg(format!("child process exited with signal {signal}"))
}
None => unreachable!("status.code() returned None but status.signal() was None"),
},
// Upon an abort, Fuchsia returns the status code ZX_TASK_RETCODE_EXCEPTION_KILL.
#[cfg(target_os = "fuchsia")]
Some(-1028) => TestResult::TrFailed,
#[cfg(not(unix))]
None => TestResult::TrFailedMsg(format!("unknown return code")),
#[cfg(any(windows, unix))]
Some(code) => TestResult::TrFailedMsg(format!("got unexpected return code {code}")),
#[cfg(not(any(windows, unix)))]
Some(_) => TestResult::TrFailed,
};
});

// If test is already failed (or allowed to fail), do not change the result.
if result != TestResult::TrOk {
Expand Down
10 changes: 9 additions & 1 deletion tests/ui/process/signal-exit-status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,28 @@
//@ ignore-wasm32 no processes
//@ ignore-sgx no processes
//@ ignore-windows
//@ ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#58590)

#![feature(core_intrinsics)]
#![cfg_attr(target_os = "fuchsia", feature(fuchsia_exit_status_aborted))]

use std::env;
use std::process::Command;

#[cfg(target_os = "fuchsia")]
use std::os::fuchsia::process::ExitStatusExt;

pub fn main() {
let args: Vec<String> = env::args().collect();
if args.len() >= 2 && args[1] == "signal" {
// Raise an aborting signal without UB
core::intrinsics::abort();
} else {
// Spawn a child process that will raise an aborting signal
let status = Command::new(&args[0]).arg("signal").status().unwrap();

#[cfg(not(target_os = "fuchsia"))]
assert!(status.code().is_none());
#[cfg(target_os = "fuchsia")]
assert!(status.aborted_code().is_some());
}
}

0 comments on commit ba47433

Please sign in to comment.