-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Disable unwinding for catch_unwind
error payloads.
#99032
Disable unwinding for catch_unwind
error payloads.
#99032
Conversation
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
(rust-highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
3061c68
to
2a7e2d7
Compare
This comment has been minimized.
This comment has been minimized.
90308c8
to
6a9a2f4
Compare
@rustbot review (cc @joshtriplett) |
r? @yaahc |
How about resume_unwind? |
cb6eb89
to
d502f6e
Compare
@nbdd0121 good catch: handling that one would require more tweaks, so it may be better to leave it for a follow-up PR, to keep each PR easier to review? |
I'd like to know how you intend to solve it. If it can't be solved, then IMO this approach would be ditched in a whole and we'd need an alternative approach. |
AIUI, this approach relies on the fact that Thus, without an approach like vtable chaining, I don't think it's possible to solve this problem purely in library code. |
For |
An extra hidden (virtual) method on |
This comment has been minimized.
This comment has been minimized.
I think it makes sense for T-libs-api to discuss whether we want such a change in the catch_unwind impl; I'm going to nominate for that purpose. There was some past discussion in T-libs it sounds like (#86027 (comment)), but not in T-libs-api, and that discussion is fairly old. I think my main concern is that this seems like a relatively invasive solution (e.g., adding some overhead to I also don't see anything immediately wrong with the Any TypeId override, but it doesn't make me particularly confident that we're not opening up some other soundness hole (e.g., some way to observe that wrapper and cause soundness problems as a result). I think it should be OK, but it doesn't inspire confidence in my eyes. Have we considered a compiler intrinsic based implementation here, that avoids the overhead by directly replacing the vtable with one where the drop_in_place is wrapped in an abort-on-unwind wrapper? |
Either way, the cost is going to be the same. The vtable needs to be codegenned if it's going to be used, because it doesn't have any state to store the old pointer. The "better" solution would be to change Footnotes
|
Ah, right. I suppose that could change if we managed to move this to the inputs of panic (e.g., resume_unwind, etc), or were willing to runtime create them, but neither seem particularly appealing. Anyway, will leave this nominated. |
This would be nice, yeah. I don't know if it's actually doable, or at least I do know that I don't know how to do it 😅. Very easily left as a follow-up PR, though, see below. Since I won't be able to attend the libs meeting, here are some notes / my take for
I'd like to nuance two things here:
So I'm kind of tempted to reverse the question: imagine if we already had
Mainly: it is very plausible that, mid-term, we end up with a compiler / With that in mind, this PR then appears to be a way to directly fix and close #86027 today, replacing the technical debt of "we have a potentially soundness-endangering footgun" with the technical debt of "we could try to make Speaking of
Footnotes
|
I think there's a lot of code using catch_unwind, but very little code that panics with some I definitely agree that we can iterate in the future so long as we're okay with the general concept of this special guard. re:soundness, I agree, it seems pretty local and correct to me :) It's just the kind of code that makes me passively unhappy. |
A did a survey a while back of ~160 crates that use |
Yeah, that makes sense -- I think surveying sites that start panics (e.g., panic!, resume_unwind, etc) would be more effective there, but the point stands. |
☔ The latest upstream changes (presumably #99917) made this pull request unmergeable. Please resolve the merge conflicts. |
f9ce33f
to
67cd60f
Compare
☔ The latest upstream changes (presumably #102051) made this pull request unmergeable. Please resolve the merge conflicts. |
This does something similar to what was suggested over rust-lang#86027 (comment) that is, to cheat a little bit and tweak/amend the `Box<dyn Any…>` obtained from `catch_unwind`: - keep the `.type_id()` the same to avoid breakage with downcasting; - but make it so the virtual `.drop_in_place()` is somehow overridden with a shim around the real drop glue that prevents unwinding (_e.g._, by aborting when that happens). This is achieved through the `DropNoUnwindSameAnyTypeId<T>`, wrapper: - with the very same layout as the `T` it wraps; - with an overridden/fake `.type_id()` so as to impersonate its inner `T`; - with a manual `impl Drop` which uses an abort bomb to ensure no unwinding can happen. That way, the `Box<DropNoUnwindSameAnyTypeId<T>>`, when box-erased to a `Box<dyn Any…>`, becomes, both layout-wise, and `type_id`-wise, undistinguishable from a `Box<T>`, thence avoiding any breakage. And yet, when that `Box<dyn Any…>` is implicitly dropped with `catch_unwind`s, no further unwinding can happen. Handle `resume_unwind` payloads too Clean up logic: centralize drop-override in catch_unwind & virtual method
Mark `panic_abort` as `no-unwind`. Co-Authored-By: Christopher Durham <[email protected]> Co-Authored-By: Gary Guo <[email protected]>
1. Fix runtime UI test that expected drop of panic payload to unwind 2. Add panic payload tests: ensure proper drop, and add one with catch_unwind 3. Add test asserting proper abort of unwind in panic payload
67cd60f
to
94118a4
Compare
☔ The latest upstream changes (presumably #102732) made this pull request unmergeable. Please resolve the merge conflicts. |
As discussed in the libs-api meeting: marking this as blocked. Let's first see where rust-lang/rfcs#3288 goes. |
Closing this as the rfc hasn't moved much in 2 years and still open with new concerns being raised. So it's going to be a long time before it gets accepted (if it even does) and unblocks this pr. It is better to create a new pr once that happens. |
Which concerns? There has only been one concern for this PR, about a minor regression w.r.t. slightly bigger |
@danielhenrymantilla uhm sorry, I meant concerns on the rfc not on this pr :D |
Fixes #86027.
This does something similar to what was suggested over #86027 (comment), that is, to tweak/amend the
Box<dyn Any…>
obtained fromcatch_unwind
:.type_id()
the same to avoid breakage with downcasting;.drop_in_place()
is somehow overridden with a shim around the real drop glue that prevents unwinding (e.g., by aborting when that happens).This is achieved through the
DropNoUnwindSameAnyTypeId<T>
, wrapper:T
it wraps;.type_id()
so as to impersonate its innerT
;impl Drop
which uses an abort bomb to ensure no unwinding can happen.That way, the
Box<DropNoUnwindSameAnyTypeId<T>>
, when box-erased to aBox<dyn Any…>
, becomes, both layout-wise, andtype_id
-wise, undistinguishable from aBox<T>
, thence avoiding any breakage.And yet, when that
Box<dyn Any…>
is implicitly dropped withcatch_unwind
s, no further unwinding can happen.Alternative implementation
FWIW, another approach to achieve the same idea would be to create one's own tweaked version of the vtable of
Any
, and directly use it to manually unsize aBox<T>
to aBox<dyn Any…>
(usingptr::from_raw_parts_mut
) to achieve what this PR automagically does withBox<Wrapper<T>>
. That being said, since the exact vtable layout ofAny
, much like the vtable layout of any trait, is only known to the compiler, this other approach could only be achieved by exploiting stdlib magic knowledge oflang
stuff. For instance, it would be brittle:Any
's definition, the vtable generation algorithm of the compiler, and this hand-rolled vtable would all three have to remain in sync at all times.catch_unwind
when catching panic-on-drop types #86027 (comment) for arguments against such alternative implementation