Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase the reach of panic_immediate_abort #117332

Merged
merged 1 commit into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions library/alloc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ compiler-builtins-c = ["compiler_builtins/c"]
compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"]
# Make panics and failed asserts immediately abort without formatting any message
panic_immediate_abort = []
9 changes: 8 additions & 1 deletion library/alloc/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,13 +377,20 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
panic!("allocation failed");
}

#[inline]
fn rt_error(layout: Layout) -> ! {
unsafe {
__rust_alloc_error_handler(layout.size(), layout.align());
}
}

unsafe { core::intrinsics::const_eval_select((layout,), ct_error, rt_error) }
#[cfg(not(feature = "panic_immediate_abort"))]
unsafe {
core::intrinsics::const_eval_select((layout,), ct_error, rt_error)
}

#[cfg(feature = "panic_immediate_abort")]
ct_error(layout)
}

// For alloc test `std::alloc::handle_alloc_error` can be used directly.
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
// ensure that the code generation related to these panics is minimal as there's
// only one location which panics rather than a bunch throughout the module.
#[cfg(not(no_global_oom_handling))]
#[inline(never)]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
fn capacity_overflow() -> ! {
panic!("capacity overflow");
}
11 changes: 7 additions & 4 deletions library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1447,7 +1447,8 @@ impl<T, A: Allocator> Vec<T, A> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap_remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("swap_remove index (is {index}) should be < len (is {len})");
}
Expand Down Expand Up @@ -1488,7 +1489,8 @@ impl<T, A: Allocator> Vec<T, A> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn insert(&mut self, index: usize, element: T) {
#[cold]
#[inline(never)]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("insertion index (is {index}) should be <= len (is {len})");
}
Expand Down Expand Up @@ -1549,7 +1551,7 @@ impl<T, A: Allocator> Vec<T, A> {
#[track_caller]
pub fn remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Killed track_caller?

Copy link
Member

@workingjubilee workingjubilee Oct 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, right. Good catch. I had noticed it but not thought much of it. Is it required to get the panic to disappear? We could #[cfg_attr(not(feature = "panic_immediate_abort"), track_caller)]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦

I deleted it because of inconsistency with all the other panic helpers. I think the better move is to add it to all the ones in that module.

fn assert_failed(index: usize, len: usize) -> ! {
panic!("removal index (is {index}) should be < len (is {len})");
Expand Down Expand Up @@ -2148,7 +2150,8 @@ impl<T, A: Allocator> Vec<T, A> {
A: Clone,
{
#[cold]
#[inline(never)]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
fn assert_failed(at: usize, len: usize) -> ! {
panic!("`at` split index (is {at}) should be <= len (is {len})");
}
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,15 +755,15 @@ impl Display for BorrowMutError {
}

// This ensures the panicking code is outlined from `borrow_mut` for `RefCell`.
#[inline(never)]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
#[cold]
fn panic_already_borrowed(err: BorrowMutError) -> ! {
panic!("already borrowed: {:?}", err)
}

// This ensures the panicking code is outlined from `borrow` for `RefCell`.
#[inline(never)]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
#[cold]
fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
Expand Down
1 change: 1 addition & 0 deletions library/core/src/panic/unwind_safe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ impl<T> DerefMut for AssertUnwindSafe<T> {
impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
type Output = R;

#[inline]
extern "rust-call" fn call_once(self, _args: ()) -> R {
(self.0)()
}
Expand Down
6 changes: 6 additions & 0 deletions library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ use iter::{MatchesInternal, SplitNInternal};
#[cold]
#[track_caller]
#[rustc_allow_const_fn_unstable(const_eval_select)]
#[cfg(not(feature = "panic_immediate_abort"))]
const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
// SAFETY: panics for both branches
unsafe {
Expand All @@ -92,6 +93,11 @@ const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
}
}

#[cfg(feature = "panic_immediate_abort")]
const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
slice_error_fail_ct(s, begin, end)
}

#[track_caller]
const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! {
panic!("failed to slice string");
Expand Down
2 changes: 1 addition & 1 deletion library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ llvm-libunwind = ["unwind/llvm-libunwind"]
system-llvm-libunwind = ["unwind/system-llvm-libunwind"]

# Make panics and failed asserts immediately abort without formatting any message
panic_immediate_abort = ["core/panic_immediate_abort"]
panic_immediate_abort = ["core/panic_immediate_abort", "alloc/panic_immediate_abort"]

# Enable std_detect default features for stdarch/crates/std_detect:
# https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
Expand Down
60 changes: 59 additions & 1 deletion library/std/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,53 @@ fn default_hook(info: &PanicInfo<'_>) {

#[cfg(not(test))]
#[doc(hidden)]
#[cfg(feature = "panic_immediate_abort")]
#[unstable(feature = "update_panic_count", issue = "none")]
pub mod panic_count {
/// A reason for forcing an immediate abort on panic.
#[derive(Debug)]
pub enum MustAbort {
AlwaysAbort,
PanicInHook,
}

#[inline]
pub fn increase(run_panic_hook: bool) -> Option<MustAbort> {
None
}

#[inline]
pub fn finished_panic_hook() {}

#[inline]
pub fn decrease() {}

#[inline]
pub fn set_always_abort() {}

// Disregards ALWAYS_ABORT_FLAG
#[inline]
#[must_use]
pub fn get_count() -> usize {
0
}

#[must_use]
#[inline]
pub fn count_is_zero() -> bool {
true
}
}

#[cfg(not(test))]
#[doc(hidden)]
#[cfg(not(feature = "panic_immediate_abort"))]
#[unstable(feature = "update_panic_count", issue = "none")]
pub mod panic_count {
use crate::cell::Cell;
use crate::sync::atomic::{AtomicUsize, Ordering};

pub const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1);
const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1);

/// A reason for forcing an immediate abort on panic.
#[derive(Debug)]
Expand Down Expand Up @@ -421,6 +462,13 @@ pub mod panic_count {
pub use realstd::rt::panic_count;

/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
#[cfg(feature = "panic_immediate_abort")]
pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
Ok(f())
}

/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
#[cfg(not(feature = "panic_immediate_abort"))]
pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
union Data<F, R> {
f: ManuallyDrop<F>,
Expand Down Expand Up @@ -755,6 +803,7 @@ fn rust_panic_with_hook(

/// This is the entry point for `resume_unwind`.
/// It just forwards the payload to the panic runtime.
#[cfg_attr(feature = "panic_immediate_abort", inline)]
pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
panic_count::increase(false);

Expand All @@ -777,7 +826,16 @@ pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
/// yer breakpoints.
#[inline(never)]
#[cfg_attr(not(test), rustc_std_internal_symbol)]
#[cfg(not(feature = "panic_immediate_abort"))]
fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
let code = unsafe { __rust_start_panic(msg) };
rtabort!("failed to initiate panic, error {code}")
}

#[cfg_attr(not(test), rustc_std_internal_symbol)]
#[cfg(feature = "panic_immediate_abort")]
fn rust_panic(_: &mut dyn PanicPayload) -> ! {
unsafe {
crate::intrinsics::abort();
}
}
Loading