Skip to content

Nested panics and std::thread::panicking #143612

Open
@purplesyringa

Description

@purplesyringa
struct Dropper;
impl Drop for Dropper {
    fn drop(&mut self) {
        catch_unwind(|| panic!()); // two panics alive at the same time
    }
}
let _dropper = Dropper;
panic!();

Should this abort? We often say that "double panics lead to abort", and I think we might even document that, but I've just found out this behavior is surprising to a lot of folks. So I want to ask for T-lang consensus: are double panics explicitly allowed if caught, and only unwinding across a landing pad leads to abort?

If double panics are allowed in this case, then everyone relying on std::thread::panicking is subtly broken. We encounter the same problem as std::uncaught_exception in C++. N4152 had to deprecate std::uncaught_exception and expose a counter instead. I think N4152 explains the problem well enough, but the TL;DR for Rust is that it's impossible to reliably implement something like ScopeGuard, because we'll either notice a panic when there's none (because std::uncaught_exception is set at the beginning anyway), or ignore a panic when it does happen (which is a problem for e.g. MutexGuard currently, see #143471). I have found some unsoundness in the wild (1, 2, 3) due to this.

I don't have a specific proposal to fix this, e.g. I don't think exposing std::thread::panic_count is a good idea, but I at least want this problem to be known.

@rustbot label +T-lang +T-libs-api +T-libs -C-discussion +A-panic

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-panicArea: Panicking machineryT-langRelevant to the language teamT-libsRelevant to the library team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions