From 38e6e5d0a9681b53cb517a3af665059e83988c3d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 26 Apr 2016 14:30:01 -0700 Subject: rustc: Use C++ personalities on MSVC Currently the compiler has two relatively critical bugs in the implementation of MSVC unwinding: * #33112 - faults like segfaults and illegal instructions will run destructors in Rust, meaning we keep running code after a super-fatal exception has happened. * #33116 - When compiling with LTO plus `-Z no-landing-pads` (or `-C panic=abort` with the previous commit) LLVM won't remove all `invoke` instructions, meaning that some landing pads stick around and cleanups may be run due to the previous bug. These both stem from the flavor of "personality function" that Rust uses for unwinding on MSVC. On 32-bit this is `_except_handler3` and on 64-bit this is `__C_specific_handler`, but they both essentially are the "most generic" personality functions for catching exceptions and running cleanups. That is, thse two personalities will run cleanups for all exceptions unconditionally, so when we use them we run cleanups for **all SEH exceptions** (include things like segfaults). Note that this also explains why LLVM won't optimize away `invoke` instructions. These functions can legitimately still unwind (the `nounwind` attribute only seems to apply to "C++ exception-like unwining"). Also note that the standard library only *catches* Rust exceptions, not others like segfaults and illegal instructions. LLVM has support for another personality, `__CxxFrameHandler3`, which does not run cleanups for general exceptions, only C++ exceptions thrown by `_CxxThrowException`. This essentially ideally matches our use case, so this commit moves us over to using this well-known personality function as well as exception-throwing function. This doesn't *seem* to pull in any extra runtime dependencies just yet, but if it does we can perhaps try to work out how to implement more of it in Rust rather than relying on MSVCRT runtime bits. More details about how this is actually implemented can be found in the changes itself, but this... Closes #33112 Closes #33116 --- src/libstd/panicking.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd') diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index fd74651bf77..b85d4b330a6 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -53,6 +53,7 @@ thread_local! { pub static PANIC_COUNT: Cell = Cell::new(0) } // // One day this may look a little less ad-hoc with the compiler helping out to // hook up these functions, but it is not this day! +#[allow(improper_ctypes)] extern { fn __rust_maybe_catch_panic(f: fn(*mut u8), data: *mut u8, -- cgit 1.4.1-3-g733a5