From 6d7ee4b4b2ac00742c291668be97dcc9a3fd1b1c Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Wed, 20 Jul 2022 12:46:40 +0200 Subject: [PATCH] Make the abort display a nicer message Mark `panic_abort` as `no-unwind`. Co-Authored-By: Christopher Durham Co-Authored-By: Gary Guo --- library/core/src/any.rs | 4 +++- library/core/src/panicking.rs | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 10b51ab22d3d2..4eef8ddca6e0b 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -245,7 +245,9 @@ impl Drop for DropNoUnwindSameAnyTypeId { impl Drop for AbortOnDrop { fn drop(&mut self) { - crate::intrinsics::abort(); + crate::panicking::panic_abort(Some(&format_args!( + "fatal runtime error: drop of the panic payload panicked" + ))) } } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index d4afe0f5326a3..d9c72d2bca626 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -90,6 +90,8 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { #[inline(never)] #[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function fn panic_no_unwind() -> ! { + // Could this be written in terms of: + // `panic_abort(Some(&format_args!("panic in a function that cannot unwind")))`? if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } @@ -109,6 +111,28 @@ fn panic_no_unwind() -> ! { unsafe { panic_impl(&pi) } } +/// Aborts the process, but with a properly displayed panic message. +#[cold] +#[rustc_allocator_nounwind] +pub(crate) fn panic_abort<'a>(message: Option<&'a fmt::Arguments<'a>>) -> ! { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + // PanicInfo with the `can_unwind` flag set to false forces an abort. + let pi = PanicInfo::internal_constructor(message, Location::caller(), false); + + // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. + unsafe { panic_impl(&pi) } +} + /// The entry point for panicking with a formatted message. /// /// This is designed to reduce the amount of code required at the call