Pluggable panic implementations (tracking issue for RFC 1513)
Tracking issue for rust-lang/rfcs#1513.
-C panic=abort is now stable, but the ability to create customized panic implementations is still unstable.
I'm working on an implementation.
Alex Crichton at 2016-04-08 23:55:44
is there a branch we can track? @alexcrichton, thanks!
Ramon Roche at 2016-04-09 00:07:40
Sure! -- https://github.com/alexcrichton/rust/tree/panic2abort
Alex Crichton at 2016-04-09 00:12:27
Will I still need a dummy
eh_personalitylang item after this goes through? Some googling suggests-Z no-landing-padswas supposed to remove the need for it (for example, this regression report led to this issue which was resolved by this PR) but I only started using Rust for OSdev since it went stable and I've always neededeh_personalityeven with-Z no-landing-pads.Thomas Winwood at 2016-04-09 00:36:05
@Ketsuban it depends. If you use any library compiled with
-C panic=unwind(like the binaries we ship) then you'll need to defineeh_personality. If, however, you compile everything with-C panic=abortthen you shouldn't need to define a personality.Alex Crichton at 2016-04-09 03:02:08
I've opened a PR for this.
Alex Crichton at 2016-04-12 02:35:23
Ah I should leave this open as the tracking issue
Alex Crichton at 2016-05-10 04:45:27
The corresponding cargo option is still missing, isn't it? From the RFC:
Add a [profile.dev] option to Cargo to disable unwinding.
Philipp Oppermann at 2016-05-13 11:51:19
@phil-opp indeed! I was just waiting for a new nightly but now I've got a PR for that as well
Alex Crichton at 2016-05-13 18:39:46
cargo PR has landed. should this be closed?
Steve Klabnik at 2016-06-04 20:15:26
Nah this is sticking around as the tracking issue for panic runtimes in general. Only the
-C panic=abortportion is stable, however.Alex Crichton at 2016-06-05 06:32:48
Is it intentional/known that anything with
plugin = true(i.e. has--crate-type dylib -C prefer-dynamicon the command line to rustc) doesn't work in combination with-C panic=abort?Aidan Hobson Sayers at 2016-06-12 02:26:22
@aidanhs I believe that's https://github.com/rust-lang/cargo/issues/2738
Alex Crichton at 2016-06-12 10:12:59
The only remaining thing here is the stable mechanism for plugging in new unwinders, which is not a priority.
Brian Anderson at 2016-08-29 21:27:34
And which should probably wait for some needs-provides functionality to be implemented or avoided.
John Ericson at 2016-08-30 17:59:48
Once we have transparently rebuildable std, I'd like to remove the Cargo option from profile. The other profile options do not (to my knowledge) change ABI or semantics so it is inconsistent to put the panic strategy in there. The target spec as per https://github.com/rust-lang/rust/issues/36647 is a better home for the time being.
John Ericson at 2016-10-04 15:42:23
Once we have transparently rebuildable std, I'd like to remove the Cargo option from profile.
What would be the ideal way to pick the panic strategy then? Would it be something like this? (assuming abort is the default and you want to switch to panic=unwind):
- executable that depends on
std. Liststdas dependency but enablestd's "unwind" Cargo feature - executable that doesn't depends on
std. Either depend on thepanic_unwindcrate or some other crate that provides an unwinder. - library that wants to indicate that relies on unwinding: depend on
stdwith the "unwind" feature enabled or depend onpanic_unwind.
Plus some magic attribute in
panic_unwindthat causes Cargo to compile everything (std included) with landing pads.Jorge Aparicio at 2016-10-05 20:00:27
- executable that depends on
@Ericson2314
Once we have transparently rebuildable std, I'd like to remove the Cargo option from profile.
How would that work? Leaving aside the issue that it would be a breaking change, per-profile panic strategies are useful: For unit tests you need
panic=unwindif you have#[should_panic]tests, but having unit tests is certainly not mutually exclusive with wantingpanic=abortin release builds.Hanna Kruppe at 2016-10-05 20:06:31
Here are some ideas:
For the low-level panic ABI stuff (abort/unwinding)
I've been thinking that crates should be able to assert a cfg/scenario formula, and that this formula can be used during dependency solving.
[lib]/[bin]/[test]/whatever can each have their own formulas. The panic-abi stuff, since it is part of the target, can be mentioned in those formulas.Additionally,
[bin],[test], etc, since they form a depenency root, could be allowed to specify a default target inline, which could be a diff on one of the built-in defaults.For high-level strategies
@japaric that's the basic idea, but a proper-needs provides solution should make that slicker. https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst is a proposal for Haskell that basically gives it parameterized packages. For "global/singleton" things panic strategies and log, we need to make a "needer" package for them that must be instantiated exactly 1 way in the install plan.
It's a huge undertaking (Backpack is a PHD thesis), but would be the pinnacle of everything we are trying to do build-system-wise for exotic platform development.
John Ericson at 2016-10-05 20:29:49
cc @japaric is this fully done now that
#[panic_handler]is stabilized? should we close?Mazdak Farrokhzad at 2018-09-15 09:30:44
@Centril That depends on whether we want to use this issue to track a stable mechanism for implementing unwinding in
no_std(right now you have to use the unstableeh_personalitylang item), or if we want to do that in another issue, perhaps in a rust-lang/rfcs issue.Jorge Aparicio at 2018-09-15 14:22:03
@japaric can you raise this on internals perhaps (and close this issue after...)? I'd like to avoid reusing tracking issues and rather keep their scope tightly delimited.
Mazdak Farrokhzad at 2018-09-15 16:37:38
@japaric any update on this?
Dylan DPC at 2019-12-22 16:58:03
Lang discussed this today in a backlog bonanza meeting, and generally those in the room were not aware of desire for replacement panic implementations (beyond switching between abort/unwind). It also seemed likely that it may make sense to expect a new RFC if such a desire exists. Please chime in on this issue if you do have a use case!
In the meantime, before such interest and/or design work, it seems like the implementation details that let us have two runtimes (panic=unwind and panic=abort) are roughly perma-unstable.
Mark Rousskov at 2022-01-19 18:51:35
Having worked on unwinding-related things recently, I see the panic runtimes as an implementation detail of std to support
-C panic=XXX. While there are use cases for supporting unwinding onno_std, this is outside the scope of this RFC/tracking issue. I think this issue should be closed to indicate that it will remain permanently unstable: there is nothing left to track.Amanieu d'Antras at 2022-01-19 19:01:33
I think we often keep the tracking issue open, but we did tag it as "perma-unstable".
Niko Matsakis at 2022-01-20 20:12:57
With
extern "C-unwind"stabilized you can now create your own#[panic_handler]implementation that does unwinding. This doesn't apply to std programs though as libstd defines#[panic_handler]already.bjorn3 at 2023-07-15 13:19:38
The unstable
core::panickingmodule also contains the very helpfulpanic_nounwind_fmtfunction which calls the custom panic handler without unwinding, which seems quite useful to get the panic handlers pretty message without the code size cost for unwinding.Could
-Cpanicperhaps be expanded in the future fromabortandunwindto a middle-groundno-unwindoption that uses thepanic_nounwind*functions to expose this behaviour to end users?Juniper Tyree at 2023-12-14 12:26:49
-Cpanic=no-unwindwould be-Cpanic=abortexcept without producing a backtrace, right? The same panic handler is used between-Cpanic=unwindand-Cpanic=abortand without recompiling libstd (or avoiding libstd entirely and defining your own panic handler), it is not possible to get rid of the backtrace functionality.panic_nounwind_fmtforces the-Cpanic=abortbehavior for that particular panic call. This will still produce a backtrace when using libstd's panic handler. By the way there is currently no cfg in libstd to disable just the backtrace, we do havepanic_immediate_abort, but that also skips the panic message and panic hook and instead codegens every panic as an abort instruction.bjorn3 at 2023-12-14 12:39:12
Thank you for your helpful and detailed reply!
-Cpanic=no-unwindwould be-Cpanic=abortexcept without producing a backtrace, right?Yes, the behaviour I’m looking for is that a panic would immediately call the panic handler (without unwinding the stack), assuming that the panic handler calls abort/exit when it completes. If another panic is invoked while running the panic handler, we would now abort immediately.
Perhaps I misunderstood
-Cpanic=abortso far - is that what it does already? I thought it worked likepanic_immediate_abortand produced a call to abort without going through the panic handler first.without recompiling libstd (or avoiding libstd entirely and defining your own panic handler), it is not possible to get rid of the backtrace functionality.
My particular use case is a NVPTX kernel, where I was experimenting with getting nice print and panic messages to work without pulling in the entire unwinding machinery. Thankfully I’m already defining a custom panic handler here, which just display formats the panic info.
Juniper Tyree at 2023-12-14 15:39:28
Perhaps I misunderstood -Cpanic=abort so far - is that what it does already?
Correct.
-Cpanic=abortwill still call the panic handler. It merely stops the panic handler from unwinding.Thankfully I’m already defining a custom panic handler here, which just display formats the panic info.
In that case panic=abort should be enough.
bjorn3 at 2023-12-14 15:46:39
In that case panic=abort should be enough.
In my
.cargo/config.tomlfile, I have the following:[target.nvptx64-nvidia-cuda] rustflags = ["-Cpanic=abort", "-Clink-args=--arch sm_35"] [unstable] build-std = ["core", "alloc", "std", "panic_abort"] build-std-features = []The inclusion of
stdinsidebuild-stdis necessary to not produce many "duplicate lang item in cratecore" errors (the same code is compiled twice, once for the host and once for the kernel, where the kernel is no-std but the host uses std).When I invoke
panic!("hi")inside my kernel, the generated PTX explodes, mostly becausecore::panicking::panic_fmtnow callsrust_begin_unwind, which is a huge function by itself and seems to pull in someVecgrowth code. Whilerust_begin_unwindeventually calls my panic handler, this extra code seems to do something which goes against my intuition that "panic=abortmeans apanic!()will immediately call the panic handler". Am I not configuring my compilation correctly or am I still misunderstanding something?Thank you again so much for your help <3
Juniper Tyree at 2023-12-16 11:44:28
The function marked as
#[panic_handler]will get the symbol name rust_begin_unwind. Are you sure you defined this function yourself and didn't pull in libstd for the binary compiled for nvptx?bjorn3 at 2023-12-16 11:50:16
I finally figured out what was going on - I was simultaneously experimenting with inlining inside the kernel as well, which pulled some string formatting code into the
rust_begin_unwindfunction. Once I got forceful inlining to work, the optimiser can now look through thepanic!("hi")expansion and see that no dynamic formatting (withformat!) is needed inside the panic handler to print the message. This eliminates all string formatting code fromrust_begin_unwind, which I originally mistook for being part of some unwinding routine. So finally the PTX assembly code is as clean as expected!Thank you so much @bjorn3 for your patient help in figuring out rust was already doing what I wanted all along :D
Juniper Tyree at 2023-12-16 14:06:18