-
Notifications
You must be signed in to change notification settings - Fork 18
Should we add an panic interface that reports the error via the panic handler but unconditionally aborts? #34
Comments
The current way library authors do this is: macro_rules! panic_abort {
($fmt:expr $(, $args:expr)* $(,)?) => {{
struct StopUnwind;
impl Drop for StopUnwind {
fn drop(&mut self) {
panic!("treating panic as abort");
}
}
let _abort = StopUnwind;
panic!($fmt $(, $args)*);
}};
}
fn main() {
panic_abort!("...");
} |
Firefox wound up with a variety of macros in C++ to cover a range of possibilities:
(After typing that all out I realize that this is not exactly the same topic but I'm going to leave this here because it might be informative to someone.) We always built Firefox with C++ exceptions disabled, which meant we had to audit STL data structure implementations to ensure that they were safe for use without exceptions. We also had issues with ObjC exceptions and wound up with an unfortunate set of macros to wrap all Cocoa API accesses with the ObjC equivalent of Question: assuming a |
My expectation is that it would work the same as if that single panic had been compiled with |
I must admit, I'm a little I'm unsure1 what the situation where you need to abort (you cannot panic) but are still in a position where it's fine to call an arbitrary panic handler (particuarly one set by safe code...). Personally, I've wanted an aborting-panic many times, but in most of them I need to abort because I have hard limitations on what functions can be called, as it may be unsafe to call an arbitrary panic handler written by safe code -- If I could call arbitrary code, I'd just panic. Some examples are:
In either of these cases, calling the panic hook and handler are not good ideas, because that stuff isn't likely to be prepared for this. Certainly, the panic hook is not, as it is set by safe code. We can still do some stuff though, such as can print out a message out (using This all may sound niche, but low level code hits it a lot I think (it's common enough that off the top, both
It's worth noting that the Firefox crash reporter is probably a separate process, so it wouldn't really be an example of a case that wants its panic handler called before an abort. In-process crash reporters exist, but (for langs without a runtime) they generally are running as signal handlers, but, well, see the limitations above. Footnotes
|
the example that came up recently was wishing we could panic instead of abort from safety checks that are essentially debug asserts contributed in rust-lang/rust#92686 I also vaguely remember some case where we had an async application running on tokio and we had certain tasks that when they panicked we wanted it to take down the whole system immediately, but the way the panics were caught and propagated significantly delayed the teardown. That said, I can't recall why this was and I wouldn't be surprised if the issue was specific to that application's architecture rather than being a general issue with panic propagation latency across task/thread boundaries. |
Ah, this is a general issue with
Hm, according to https://github.com/rust-lang/rust/pull/92686/files#diff-7e8efe3110a5b74834b0a6e63768df9982c1599758a6634337ce356a0e22e0f4R1994 it's about code size. While I actually think there's are likely improvements1 we can do to reduce the cost of panic handling... But I don't think this is ever not going to be the case for these sorts of checks. It's going to be hard to get anywhere near to Footnotes
|
My assumption was the codesize concern has to do with the landing pads or w/e that get generated to help with unwinding, not the actual invocation of the panic handler to report an error. Also, fwiw you lost me on the second half of this paragraph 😅, not sure what PIC/GOT/PLT mean. |
Yep, lots of code size issues arise from landing pads. A noreturn nounwind call wouldn't be terribly bad. PLT shouldn't matter here, but if you enable PIC in x86 then there might be a thunk call due to lack of PC-relative encoding. In x64 or other archs there are PC-relative encoding, so even with PIC the code size should still be reasonable. |
Sorry. I mean the overhead associated with position independent code (PIC) and dynamic loading and linking. To handwave a bit the GOT (global offset table) and PLT (procedure linkage table) are functionality associated with this which may make a function calls somewhat more costly in code size, especially when compared to The functions where those checks are used seemed quite important, so it seems plausible to me that the overhead would add up, but it's certainly possible I'm overestimating the impact on modern systems, or underestimating the size cost of the landing pads. Anyway I'm not sure any of that actually matters for this issue. I thought of a better explanation for my position, and why I found it surprising that this would run the hook. It boils down to that I consider Essentially, I see these as APIs which are for indicating two different types of errors:
Now, under this lens, I see A aborting-panic that behaves like So I think we should have a pretty good reason not to want to support case 2. (And if we decide that's not a supported use case, we should document this fact clearly, as it seems pretty surprising otherwise) Hopefully that made a little more sense. Sorry for how long it was, and if I said anything twice) Footnotes
|
I think I agree with @thomcc's summary of affairs, but also:
Aside: Firefox does have an in-process exception handler for crashes that are not happening in a child process with a parent to handle them, but it's not a Rust panic handler because it wants to handle all sorts of signals/exceptions/etc, so it's not really germane to the discussion here. |
I think it's obligatory for me to reference rust-lang/rust#92988 in case you aren't aware of that. We already have an aborting panic mechanism in place as part of project-ffi-unwind, this is currently used to report unwind in a context that unwinding is forbidden (e.g. |
Yeah, this is how I think @Amanieu wants aborting panics to work. You just annotate the function with the proper attribute to prevent unwinding then invoke the normal panic. Also, I went ahead and changed the title to make it clear this is more of an open question than a proposal, since I don't want people to worry that I'm pushing this in a certain direction. |
For us following along at home, what are |
I believe those are C++ libraries, basically google and facebook's supplemental c++ std libraries, sorta like boost. |
A slightly smaller alternative would be to provide a But (The shim can be adjusted to not rely on it either by writing |
Right now panic behavior is defined by binary authors and is applied globally for an application. This can mean either all
panic!
s abort the application or that all panics unwind the application. This design can cause issues for library authors where they need to assume that any panic they invoke could potentially start unwinding, requiring library authors to plan for exception safety. They can work around this by directly aborting the application withstd::process::exit
, but this means they're no longer leveraging the same panic reporting logic that the rest of the application is.The error handling project group should look into adding an interface for panics that always causes an aborting panic, even if the rest of the application has been compiled with
panic = unwind
.The text was updated successfully, but these errors were encountered: