-
Notifications
You must be signed in to change notification settings - Fork 19
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
ACP: panic::abort_unwind #441
Comments
LGTM. I think this is worth having. One thing that makes this strange is libcore does not currently expose any stable |
Accepting this together with #442. (But they can be implemented and tracked independently, and perhaps stabilized independently.) I wonder if there will be any reason to have separate |
This seems highly unlikely. Existing usages of If someone absolutely must |
Add `core::panic::abort_unwind` `abort_unwind` is like `catch_unwind` except that it aborts the process if it unwinds, using the `#[rustc_nounwind]` mechanism also used by `extern "C" fn` to abort unwinding. The docs attempt to make it clear when to (rarely) and when not to (usually) use the function. Although usage of the function is discouraged, having it available will help to normalize the experience when abort_unwind shims are hit, as opposed to the current ecosystem where there exist multiple common patterns for converting unwinding into a process abort. For further information and justification, see the linked ACP. - Tracking issue: rust-lang#130338 - ACP: rust-lang/libs-team#441
Rollup merge of rust-lang#130339 - CAD97:unwind-choice, r=dtolnay Add `core::panic::abort_unwind` `abort_unwind` is like `catch_unwind` except that it aborts the process if it unwinds, using the `#[rustc_nounwind]` mechanism also used by `extern "C" fn` to abort unwinding. The docs attempt to make it clear when to (rarely) and when not to (usually) use the function. Although usage of the function is discouraged, having it available will help to normalize the experience when abort_unwind shims are hit, as opposed to the current ecosystem where there exist multiple common patterns for converting unwinding into a process abort. For further information and justification, see the linked ACP. - Tracking issue: rust-lang#130338 - ACP: rust-lang/libs-team#441
Couldn't it use |
On Windows, using On Itanium EH targets (e.g. Linux), an unwind without any catch target will fail to start (by the spec). Currently Rust reserves the right to abort before the unwind when an unwind would end with a runtime-introduced abort, but this isn't a great user experience. It could be acceptable for unwinding from the drop of a panic payload, if the error improves from “fatal runtime error: failed to initiate panic, code 5”. (Unfortunately, |
Proposal
Problem statement
Various use cases exist that can't or don't want to support being unwound through. Today, there are multiple ways of coverting an in-progress unwind into an abort, each with subtly different user experience when the abort occurs. By providing a function
abort_unwind
as part of core, we can standardize the experience.Motivating examples or use cases
Perhaps the most notorious case of unwind-abort is the take_mut/replace_with pattern. The
take_mut
crate usescatch_unwind
to respond to unwinds. Thereplace_with
crate uses drop flag conditional drop glue to respond to unwinds. Both crates simply callabort
on an unwind and don't show a more specific reason for what caused the abort.Also highly notable is the soundness footgun that dropping the panic payload returned from
catch_unwind
can itself cause an unwind. std necessarily usescatch_unwind
1 and responds to an unwind withrtabort!
.I myself have used
impl Drop
types to cause a deliberate double panic (and thus an abort) in code that cannot soundly repair state when it gets unwound. This strategy generally creates a more useful crash message, as the runtime can see that the unwind will not be completed.Solution sketch
The newly stabilized abort on
extern "C"
edges (“panic in a function that cannot unwind”) is the exact handling that we would like to have for all code regions that cannot be unwound. We also havecatch_unwind
already establishing the API shape of establishing an unwind handler.Alternatives
We can always do nothing; existing solutions in the ecosystem are sufficient. However, the way that this is usually done results in suboptimal diagnostics on an abort, and the required user code required to be sound is “obvious” enough that pulling in a 3rd party crate is unlikely.
I've chosen to use an inner function with
extern "C"
such that the public API signature doesn't show this implementation choice. It would be a valid choice to skip this step, and/or to use the#[rustc_nounwind]
attribute instead of ABI.Similarly, the language could provide a public
#[nounwind]
attribute to prevent unwinding instead ofabort_unwind
being library API. I argue that providing the library API is the better choice since the added friction discouraging the use of nounwind shims is a good thing overall.Links and related work
I have participated in wg-unwind, but this is my own individual idea.
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
Second, if there's a concrete solution:
Footnotes
There needs to be at least one catch frame on the stack to ensure that raising an unwind can actually unwind the stack. ↩
The text was updated successfully, but these errors were encountered: