Skip to content

Commit 4e2c43c

Browse files
Correct handle -C panic=abort in doctests
1 parent 560d450 commit 4e2c43c

File tree

3 files changed

+71
-17
lines changed

3 files changed

+71
-17
lines changed

src/librustdoc/doctest.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ mod rust;
77
use std::fs::File;
88
use std::hash::{Hash, Hasher};
99
use std::io::{self, Write};
10+
#[cfg(unix)]
11+
use std::os::unix::process::ExitStatusExt;
1012
use std::path::{Path, PathBuf};
1113
use std::process::{self, Command, Stdio};
1214
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -849,13 +851,40 @@ fn run_test(
849851
} else {
850852
cmd.output()
851853
};
854+
855+
// FIXME: Make `test::get_result_from_exit_code` public and use this code instead of this.
856+
//
857+
// On Zircon (the Fuchsia kernel), an abort from userspace calls the
858+
// LLVM implementation of __builtin_trap(), e.g., ud2 on x86, which
859+
// raises a kernel exception. If a userspace process does not
860+
// otherwise arrange exception handling, the kernel kills the process
861+
// with this return code.
862+
#[cfg(target_os = "fuchsia")]
863+
const ZX_TASK_RETCODE_EXCEPTION_KILL: i32 = -1028;
864+
// On Windows we use __fastfail to abort, which is documented to use this
865+
// exception code.
866+
#[cfg(windows)]
867+
const STATUS_FAIL_FAST_EXCEPTION: i32 = 0xC0000409u32 as i32;
868+
#[cfg(unix)]
869+
const SIGABRT: std::ffi::c_int = 6;
852870
match result {
853871
Err(e) => return (duration, Err(TestFailure::ExecutionError(e))),
854872
Ok(out) => {
855-
if langstr.should_panic && out.status.code() != Some(test::ERROR_EXIT_CODE) {
856-
return (duration, Err(TestFailure::UnexpectedRunPass));
857-
} else if !langstr.should_panic && !out.status.success() {
873+
if !langstr.should_panic && !out.status.success() {
858874
return (duration, Err(TestFailure::ExecutionFailure(out)));
875+
} else if langstr.should_panic {
876+
match out.status.code() {
877+
Some(test::ERROR_EXIT_CODE) => {}
878+
#[cfg(windows)]
879+
Some(STATUS_FAIL_FAST_EXCEPTION) => {}
880+
#[cfg(unix)]
881+
None if out.status.signal() == Some(SIGABRT) => {}
882+
// Upon an abort, Fuchsia returns the status code
883+
// `ZX_TASK_RETCODE_EXCEPTION_KILL`.
884+
#[cfg(target_os = "fuchsia")]
885+
Some(ZX_TASK_RETCODE_EXCEPTION_KILL) => {}
886+
_ => return (duration, Err(TestFailure::UnexpectedRunPass)),
887+
}
859888
}
860889
}
861890
}

src/librustdoc/doctest/runner.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,6 @@ mod __doctest_mod {{
129129
130130
pub static BINARY_PATH: OnceLock<PathBuf> = OnceLock::new();
131131
pub const RUN_OPTION: &str = \"RUSTDOC_DOCTEST_RUN_NB_TEST\";
132-
pub const SHOULD_PANIC_DISABLED: bool = (
133-
cfg!(target_family = \"wasm\") || cfg!(target_os = \"zkvm\")
134-
) && !cfg!(target_os = \"emscripten\");
135132
136133
#[allow(unused)]
137134
pub fn doctest_path() -> Option<&'static PathBuf> {{
@@ -146,11 +143,32 @@ mod __doctest_mod {{
146143
.output()
147144
.expect(\"failed to run command\");
148145
if should_panic {{
149-
if out.status.code() != Some(test::ERROR_EXIT_CODE) {{
150-
eprintln!(\"Test didn't panic, but it's marked `should_panic`.\");
151-
ExitCode::FAILURE
152-
}} else {{
153-
ExitCode::SUCCESS
146+
// FIXME: Make `test::get_result_from_exit_code` public and use this code instead of this.
147+
//
148+
// On Zircon (the Fuchsia kernel), an abort from userspace calls the
149+
// LLVM implementation of __builtin_trap(), e.g., ud2 on x86, which
150+
// raises a kernel exception. If a userspace process does not
151+
// otherwise arrange exception handling, the kernel kills the process
152+
// with this return code.
153+
#[cfg(target_os = \"fuchsia\")]
154+
const ZX_TASK_RETCODE_EXCEPTION_KILL: i32 = -1028;
155+
// On Windows we use __fastfail to abort, which is documented to use this
156+
// exception code.
157+
#[cfg(windows)]
158+
const STATUS_FAIL_FAST_EXCEPTION: i32 = 0xC0000409u32 as i32;
159+
#[cfg(unix)]
160+
const SIGABRT: std::ffi::c_int = 6;
161+
162+
match out.status.code() {{
163+
Some(test::ERROR_EXIT_CODE) => ExitCode::SUCCESS,
164+
#[cfg(windows)]
165+
Some(STATUS_FAIL_FAST_EXCEPTION) => ExitCode::SUCCESS,
166+
#[cfg(unix)]
167+
None if out.status.signal() == Some(libc::SIGABRT) => ExitCode::SUCCESS,
168+
// Upon an abort, Fuchsia returns the status code ZX_TASK_RETCODE_EXCEPTION_KILL.
169+
#[cfg(target_os = \"fuchsia\")]
170+
Some(ZX_TASK_RETCODE_EXCEPTION_KILL) => ExitCode::SUCCESS,
171+
_ => ExitCode::FAILURE,
154172
}}
155173
}} else if !out.status.success() {{
156174
if let Some(code) = out.status.code() {{

tests/run-make/rustdoc-should-panic/rmake.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@
55

66
use run_make_support::rustdoc;
77

8-
fn check_output(output: String, edition: &str) {
8+
fn check_output(edition: &str, panic_abort: bool) {
9+
let mut rustdoc_cmd = rustdoc();
10+
rustdoc_cmd.input("test.rs").arg("--test").edition(edition);
11+
if panic_abort {
12+
rustdoc_cmd.args(["-C", "panic=abort"]);
13+
}
14+
let output = rustdoc_cmd.run_fail().stdout_utf8();
915
let should_contain = &[
1016
"test test.rs - bad_exit_code (line 1) ... FAILED",
1117
"test test.rs - did_not_panic (line 6) ... FAILED",
@@ -26,11 +32,12 @@ Test didn't panic, but it's marked `should_panic`.",
2632
}
2733

2834
fn main() {
29-
check_output(rustdoc().input("test.rs").arg("--test").run_fail().stdout_utf8(), "2015");
35+
check_output("2015", false);
3036

3137
// Same check with the merged doctest feature (enabled with the 2024 edition).
32-
check_output(
33-
rustdoc().input("test.rs").arg("--test").edition("2024").run_fail().stdout_utf8(),
34-
"2024",
35-
);
38+
check_output("2024", false);
39+
40+
// Checking that `-C panic=abort` is working too.
41+
check_output("2015", true);
42+
check_output("2024", true);
3643
}

0 commit comments

Comments
 (0)