From: Ralf Jung Date: Tue, 26 Nov 2019 09:23:45 +0000 (+0100) Subject: mention resume_panic entry point X-Git-Url: https://git.ralfj.de/web.git/commitdiff_plain/5cb6ce8166d734bba4cfa53d12d7d45380f7f3aa?ds=inline;hp=7834da2ccb92d1b9a9af4d0df1559b764a982e12 mention resume_panic entry point --- diff --git a/ralf/_posts/2019-11-25-how-to-panic-in-rust.md b/ralf/_posts/2019-11-25-how-to-panic-in-rust.md index 0a9d2ba..3aa147a 100644 --- a/ralf/_posts/2019-11-25-how-to-panic-in-rust.md +++ b/ralf/_posts/2019-11-25-how-to-panic-in-rust.md @@ -71,7 +71,7 @@ On top of the panic *runtime* interface, libstd implements the default Rust pani #### `rust_panic_with_hook` -The key function that everything passes through is [`rust_panic_with_hook`](https://github.com/rust-lang/rust/blob/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8/src/libstd/panicking.rs#L435-L437): +The key function that almost everything passes through is [`rust_panic_with_hook`](https://github.com/rust-lang/rust/blob/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8/src/libstd/panicking.rs#L435-L437): {% highlight rust %} fn rust_panic_with_hook( payload: &mut dyn BoxMeUp, @@ -96,7 +96,7 @@ The `'static` bound is quite well hidden there, but after a while I realized tha #### libstd panicking entry points -`rust_panic_with_hook` is a private function to `std::panicking`; the module provides three separate entry points on top of this central function: +`rust_panic_with_hook` is a private function to `std::panicking`; the module provides three entry points on top of this central function, and one that circumvents it: * the [default panic handler implementation](https://github.com/rust-lang/rust/blob/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8/src/libstd/panicking.rs#L301), backing (as we will see) panics from `core::panic!` and built-in panics (from arithmetic overflow or out-of-bounds array/slice indexing). This obtains as input a [`PanicInfo` ](https://doc.rust-lang.org/core/panic/struct.PanicInfo.html), and it has to turn that into arguments for `rust_panic_with_hook`. @@ -119,6 +119,11 @@ The `'static` bound is quite well hidden there, but after a while I realized tha In particular, a panic hook that looks at the `message` field of the `PanicData` it is passed will *not* be able to see the message in a `std::panic!("do panic")`, but it *will* see the message in a `std::panic!("panic with data: {}", data)` as the latter passes through `begin_panic_fmt` instead. That seems quite surprising. (But also note that `PanicData::message()` is not stable yet.) +* [`update_count_then_panic`](https://github.com/rust-lang/rust/blob/7d761fe0462ba0f671a237d0bb35e3579b8ba0e8/src/libstd/panicking.rs#L488) is the odd one out: this entry point backs [`resume_unwind`](https://doc.rust-lang.org/nightly/std/panic/fn.resume_unwind.html), and it actually does *not* call the panic hook. + Instead, it dispatches to the panic runtime immediately. + Like, `begin_panic`, it lets the caller pick an arbitrary payload. + Unlike `begin_panic`, the caller is responsible for boxing and unsizing the payload; `update_count_then_panic` just forwards that pretty much verbatim to the panic runtime. + ## Panic Handler All of the `std::panic!` machinery is really useful, but it relies on heap allocations through `Box` which is not always available.