Skip to content

Commit 6e45564

Browse files
committed
Auto merge of #31457 - lambda:rtabort-use-libc-abort, r=alexcrichton
Use libc::abort, not intrinsics::abort, in rtabort! intrinsics::abort compiles down to an illegal instruction, which on Unix-like platforms causes the process to be killed with SIGILL. A more appropriate way to kill the process would be SIGABRT; this indicates better that the runtime has explicitly aborted, rather than some kind of compiler bug or architecture mismatch that SIGILL might indicate. For rtassert!, replace this with libc::abort. libc::abort raises SIGABRT, but is defined to do so in such a way that it will terminate the process even if SIGABRT is currently masked or caught by a signal handler that returns. On non-Unix platforms, retain the existing behavior. On Windows we prefer to avoid depending on the C runtime, and we need a fallback for any other platforms that may be defined. An alternative on Windows would be to call TerminateProcess, but this seems less essential than switching to using SIGABRT on Unix-like platforms, where it is common for the process-killing signal to be printed out or logged. This is a [breaking-change] for any code that depends on the exact signal raised to abort a process via rtabort! cc #31273 cc #31333
2 parents e24d621 + cfc3865 commit 6e45564

File tree

2 files changed

+25
-4
lines changed

2 files changed

+25
-4
lines changed

src/libstd/sys/common/util.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
use env;
1212
use fmt;
13-
use intrinsics;
1413
use io::prelude::*;
1514
use sync::atomic::{self, Ordering};
1615
use sys::stdio::Stderr;
@@ -34,9 +33,32 @@ pub fn dumb_print(args: fmt::Arguments) {
3433
let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args));
3534
}
3635

36+
// On Unix-like platforms, libc::abort will unregister signal handlers
37+
// including the SIGABRT handler, preventing the abort from being blocked, and
38+
// fclose streams, with the side effect of flushing them so libc bufferred
39+
// output will be printed. Additionally the shell will generally print a more
40+
// understandable error message like "Abort trap" rather than "Illegal
41+
// instruction" that intrinsics::abort would cause, as intrinsics::abort is
42+
// implemented as an illegal instruction.
43+
#[cfg(unix)]
44+
unsafe fn abort_internal() -> ! {
45+
use libc;
46+
libc::abort()
47+
}
48+
49+
// On Windows, we want to avoid using libc, and there isn't a direct
50+
// equivalent of libc::abort. The __failfast intrinsic may be a reasonable
51+
// substitute, but desireability of using it over the abort instrinsic is
52+
// debateable; see https://github.com/rust-lang/rust/pull/31519 for details.
53+
#[cfg(not(unix))]
54+
unsafe fn abort_internal() -> ! {
55+
use intrinsics;
56+
intrinsics::abort()
57+
}
58+
3759
pub fn abort(args: fmt::Arguments) -> ! {
3860
dumb_print(format_args!("fatal runtime error: {}\n", args));
39-
unsafe { intrinsics::abort(); }
61+
unsafe { abort_internal(); }
4062
}
4163

4264
#[allow(dead_code)] // stack overflow detection not enabled on all platforms

src/test/run-pass/out-of-stack.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ fn check_status(status: std::process::ExitStatus)
4747
use std::os::unix::process::ExitStatusExt;
4848

4949
assert!(!status.success());
50-
assert!(status.signal() != Some(libc::SIGSEGV)
51-
&& status.signal() != Some(libc::SIGBUS));
50+
assert_eq!(status.signal(), Some(libc::SIGABRT));
5251
}
5352

5453
#[cfg(not(unix))]

0 commit comments

Comments
 (0)