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

Panic handlers and order precedence? #105432

Closed
JoshLind opened this issue Dec 7, 2022 · 3 comments · Fixed by #105497
Closed

Panic handlers and order precedence? #105432

JoshLind opened this issue Dec 7, 2022 · 3 comments · Fixed by #105497
Assignees

Comments

@JoshLind
Copy link

JoshLind commented Dec 7, 2022

Reading the standard library documentation for panic, one might think that catch_unwind (https://doc.rust-lang.org/std/panic/fn.catch_unwind.html) would take precedence over any registered panic hook, i.e., if you used both catch_unwind and set_hook in a program, any unwinding panic thrown in the catch_unwind scope should be caught. But, this doesn't appear to be the case. See this simple example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a0167a26203b23f5b50efcd1478b54d7

fn bar() {
    println!("bar() is called!");
}

fn foo() {
    let res = std::panic::catch_unwind(|| {
        bar();
        panic!("Panicking after calling bar()!");
    });
    
    println!("Unwind closure returned: {:?}", res);
}

fn main() {
    std::panic::set_hook(Box::new(move |_| {
        println!("Panic handler invoked!");
        std::process::exit(12);
    }));
    
    foo();
}

I'd expect Unwind closure returned: Err(Any { .. }) to be printed, but it doesn't get printed. Instead, the panic handler is invoked.

Can you elaborate if this is the correct behaviour/intent? And if so, why? It seems to me that it would be useful to support both concurrently, i.e., allow the catch to handle the panic, and if it cannot, it could fallback to the registered handler?

@albertlarsan68
Copy link
Member

As written in https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html:

The panic hook is invoked when a thread panics, but before the panic runtime is invoked. As such, the hook will run with both the aborting and unwinding runtimes.

This means that the panic hook is run before the stack is unwound, thus before the catch_unwind catches the panic.

@JoshLind
Copy link
Author

JoshLind commented Dec 9, 2022

Hey @albertlarsan68, thanks for replying 😄

This means that the panic hook is run before the stack is unwound, thus before the catch_unwind catches the panic.

Aah, gotcha. Yeah, we managed to see this on our side, too. It might be worth having the docs make this super explicit, especially for n00bs like me (e.g., I wasn't able to infer the current behaviour from this sentence). I also assume having them operate the other way around is undesirable and/or infeasible?

@albertlarsan68
Copy link
Member

@rustbot claim

A PR to document this behavior is up at #105497

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants