From de250e5f99398a747bea384ca2c502361d1ceaee Mon Sep 17 00:00:00 2001 From: Brian Campbell Date: Sat, 6 Feb 2016 17:16:56 -0500 Subject: [PATCH 1/2] 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 --- src/libstd/sys/common/util.rs | 10 +++++++++- src/test/run-pass/out-of-stack.rs | 3 +-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/common/util.rs b/src/libstd/sys/common/util.rs index b7a6b7650d540..056069670d680 100644 --- a/src/libstd/sys/common/util.rs +++ b/src/libstd/sys/common/util.rs @@ -10,7 +10,6 @@ use env; use fmt; -use intrinsics; use io::prelude::*; use sync::atomic::{self, Ordering}; use sys::stdio::Stderr; @@ -34,7 +33,16 @@ pub fn dumb_print(args: fmt::Arguments) { let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } +#[cfg(unix)] pub fn abort(args: fmt::Arguments) -> ! { + use libc; + dumb_print(format_args!("fatal runtime error: {}\n", args)); + unsafe { libc::abort(); } +} + +#[cfg(not(unix))] +pub fn abort(args: fmt::Arguments) -> ! { + use intrinsics; dumb_print(format_args!("fatal runtime error: {}\n", args)); unsafe { intrinsics::abort(); } } diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index 4401861a1631c..58119f965cf82 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -46,8 +46,7 @@ fn check_status(status: std::process::ExitStatus) use std::os::unix::process::ExitStatusExt; assert!(!status.success()); - assert!(status.signal() != Some(libc::SIGSEGV) - && status.signal() != Some(libc::SIGBUS)); + assert_eq!(status.signal(), Some(libc::SIGABRT)); } #[cfg(not(unix))] From be07ab2f4e366aa11ed9229c4b520e04edd25316 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 9 Feb 2016 10:49:47 -0800 Subject: [PATCH 2/2] Open code the __failfast intrinsic for rtabort! on windows As described https://msdn.microsoft.com/en-us/library/dn774154.aspx This is a Windows 8+ mechanism for terminating the process quickly, which degrades to either an access violation or bugcheck in older versions. I'm not sure this is better the the current mechanism of terminating with an illegal instruction, but we recently converted unix to terminate more correctly with SIGABORT, and this *seems* more correct for windows. [breaking-change] --- src/libstd/sys/common/util.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/common/util.rs b/src/libstd/sys/common/util.rs index 056069670d680..ebf6edcc2281b 100644 --- a/src/libstd/sys/common/util.rs +++ b/src/libstd/sys/common/util.rs @@ -40,11 +40,24 @@ pub fn abort(args: fmt::Arguments) -> ! { unsafe { libc::abort(); } } -#[cfg(not(unix))] +// On windows, use the processor-specific __fastfail mechanism +// https://msdn.microsoft.com/en-us/library/dn774154.aspx +#[cfg(all(windows, target_arch = "x86"))] pub fn abort(args: fmt::Arguments) -> ! { - use intrinsics; dumb_print(format_args!("fatal runtime error: {}\n", args)); - unsafe { intrinsics::abort(); } + unsafe { + asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT + ::intrinsics::unreachable(); + } +} + +#[cfg(all(windows, target_arch = "x86_64"))] +pub fn abort(args: fmt::Arguments) -> ! { + dumb_print(format_args!("fatal runtime error: {}\n", args)); + unsafe { + asm!("int $$0x29" :: "{rcx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT + ::intrinsics::unreachable(); + } } #[allow(dead_code)] // stack overflow detection not enabled on all platforms