Code change:
// panicking thread consumes at least 2 bytes of address space. static GLOBAL_PANIC_COUNT: AtomicUsize = AtomicUsize::new(0); <ins> // 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. </ins> pub fn increase() -> (bool, usize) { <del> ( GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed) & ALWAYS_ABORT_FLAG != 0, </del> <ins> 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 { </ins> LOCAL_PANIC_COUNT.with(|c| { let next = c.get() + 1; c.set(next); next <del> }), ) </del> <ins> }) }; (must_abort, panics) </ins> } pub fn decrease() {

Related discussion:
text: Since is stored in which is not a thread-local, maybe the program could abort before using any thread-local.
It can't do that and also print the payload, because printing the payload might itself panic, and the recursive panic needs to be detected.
Maybe instead there should be a which can return None to mean "this thread-local variable has not been initialised".
I think it might be possible to use a to avoid the allocation.
Do thread-local always avoid the allocation? I think they fall back to regular thread-locals on platforms where avoiding allocations is not (easily) possible.
The version of looks basically same as the non- version when using , which will likely allocate here: Maybe the panic count could be stored directly in rather than on the heap. But is itself safe after ? If it tries to hold a lock or something it's possible to deadlock.
Should this only occur on Android? It happened on QNX as well (not yet upstreamed, work in progress so I don't trust it yet), but I can also reproduce it on with a simple patch (disables thread local storage): Would this be a target spec where we would expect to succeed?
Interesting. To be honest, I'm not sure. I do know that modern libc doctrine is that allocation after fork is UB. The test case is checking that we can safely panic after fork, and abort, without UB. This ought to work due to . I think that every failure of this test case is a real bug. Solving those bugs is not so easy because the machinery inside panic uses thread-local state which apparently is really super hard to make work without allocating or taking locks.
Yes, allocating memory is UB, same as working with mutexes. In case our setups are okay (i.e. having and using fork etc.), I also see this is a bug. Maybe we don't need to fix the issue with the thread-local state (if at all possible): calls to get the number recursive panics and if we . : determines using --works determines number recursive panics using TLS --allocates after --UB first: If it is true, it will always call -- the process will be killed very very soon by the OS In case of a recursion, a hardcoded-string is printed; otherwise additionally Do we really need to correctly determine a recursion, or can we allow "false positives"?