diff options
| author | Ralf Jung <post@ralfj.de> | 2022-10-21 10:18:54 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2022-10-21 10:18:54 +0200 |
| commit | 9b57a2f55a76fa1e3d000932e0a708adb587990c (patch) | |
| tree | 53c592b83ed6929eb66beb179586d09409fc3088 /library/std/src/panicking.rs | |
| parent | 53e357748675b387b6d25fe563b960cb7a7a0aea (diff) | |
| parent | b1ab3b738ac718da74cd4aa0bb7f362d0adbdf84 (diff) | |
| download | rust-9b57a2f55a76fa1e3d000932e0a708adb587990c.tar.gz rust-9b57a2f55a76fa1e3d000932e0a708adb587990c.zip | |
merge rustc history
Diffstat (limited to 'library/std/src/panicking.rs')
| -rw-r--r-- | library/std/src/panicking.rs | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 38dcf6cbf7d..d4976a469cc 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -300,7 +300,7 @@ pub mod panic_count { thread_local! { static LOCAL_PANIC_COUNT: Cell<usize> = const { Cell::new(0) } } // Sum of panic counts from all threads. The purpose of this is to have - // a fast path in `is_zero` (which is used by `panicking`). In any particular + // a fast path in `count_is_zero` (which is used by `panicking`). In any particular // thread, if that thread currently views `GLOBAL_PANIC_COUNT` as being zero, // then `LOCAL_PANIC_COUNT` in that thread is zero. This invariant holds before // and after increase and decrease, but not necessarily during their execution. @@ -308,6 +308,14 @@ pub mod panic_count { // Additionally, the top bit of GLOBAL_PANIC_COUNT (GLOBAL_ALWAYS_ABORT_FLAG) // records whether panic::always_abort() has been called. This can only be // set, never cleared. + // panic::always_abort() is usually called to prevent memory allocations done by + // the panic handling in the child created by `libc::fork`. + // Memory allocations performed in a child created with `libc::fork` are undefined + // behavior in most operating systems. + // Accessing LOCAL_PANIC_COUNT in a child created by `libc::fork` would lead to a memory + // allocation. Only GLOBAL_PANIC_COUNT can be accessed in this situation. This is + // sufficient because a child process will always have exactly one thread only. + // See also #85261 for details. // // This could be viewed as a struct containing a single bit and an n-1-bit // value, but if we wrote it like that it would be more than a single word, @@ -318,15 +326,26 @@ pub mod panic_count { // panicking thread consumes at least 2 bytes of address space. static GLOBAL_PANIC_COUNT: AtomicUsize = AtomicUsize::new(0); + // Return the state of the ALWAYS_ABORT_FLAG and number of panics. + // + // If ALWAYS_ABORT_FLAG is not set, the number is determined on a per-thread + // base (stored in LOCAL_PANIC_COUNT), i.e. it is the amount of recursive calls + // of the calling thread. + // If ALWAYS_ABORT_FLAG is set, the number equals the *global* number of panic + // calls. See above why LOCAL_PANIC_COUNT is not used. pub fn increase() -> (bool, usize) { - ( - GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed) & ALWAYS_ABORT_FLAG != 0, + let global_count = GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed); + let must_abort = global_count & ALWAYS_ABORT_FLAG != 0; + let panics = if must_abort { + global_count & !ALWAYS_ABORT_FLAG + } else { LOCAL_PANIC_COUNT.with(|c| { let next = c.get() + 1; c.set(next); next - }), - ) + }) + }; + (must_abort, panics) } pub fn decrease() { @@ -369,7 +388,7 @@ pub mod panic_count { } // Slow path is in a separate function to reduce the amount of code - // inlined from `is_zero`. + // inlined from `count_is_zero`. #[inline(never)] #[cold] fn is_zero_slow_path() -> bool { |
