-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Do not allocate or unwind after fork #81858
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this also work for vfork?
vfork is more tricky, because anything you mutate in the child stays mutated (or may do - some people provide a vfork which is just fork...) I think allocation is still potentially unsafe because you may deadlock with your suspended parent, and the thread ids or TLS etc. may make no sense to your allocator. So you still want to be able to avoid allocation and this MR achieves that. There's the additional complication that with vfork, setting the panic hook affects the parent too. You'd have to Do Something about that. Maybe check the pid in your hook. So I think this MR makes it easier to DTRT for vfork, but I haven't thought about it thoroughly. In particular I'm not sure if even after this MR, it is possible to arrange for it to be safe to panic after vfork. |
This comment has been minimized.
This comment has been minimized.
05acb1c
to
b925978
Compare
This comment has been minimized.
This comment has been minimized.
b925978
to
2a18575
Compare
Rebased onto master and fixed the trivial merge conflict. |
This comment has been minimized.
This comment has been minimized.
fca912b
to
139801d
Compare
Rebased onto master and fixed the trivial merge conflict. |
This comment has been minimized.
This comment has been minimized.
139801d
to
4f26b2b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds quite a large API surface area for a very niche issue. It'd be great to make panicking after fork safer, but I'm not sure if it's worth it to add so many new things for it. Maybe there's a simpler way that would be good enough?
A big part of the api (the raw_hook) is only there to avoid the allocation of a String
after a panic!()
with formatting arguments, right? The alternative would be to only have this work for panic!("literal without arguments")
, which does not allocate before the hook is executed. That won't work on Result::unwrap()
though. (But it would for Option::unwrap()
.)
Not sure how/if we could do this, but maybe we could instead make a way to fully disable the global allocator. Replace it with one that won't (de)allocate anything anymore. That would prevent a lot more misusages in pre_exec, and we could have the panic handler skip allocating the String before calling the hook, if allocation fails.
// We wrap this so that we never return 0, which would cause | ||
// std::io::write_all et al to box to create a WriteZero error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've opened #83353 to fix this.
Another idea would be to be able to set some kind of flag (or set |
This comment has been minimized.
This comment has been minimized.
@ijackson Ping from triage! Any updates on this? Also, there's merge conflict now. |
Hi. Thanks for the ping. I may be able to look at this today... |
I think this would be ideal. However it is really tough. The existing compile-time indirections boil each call to the allocator down to a call to |
I tried this approach and it worked very well with very little code. I chose to steal a bit out of the top of the thread-local |
4f26b2b
to
3c230ae
Compare
@bors retry |
@bors r- r=m-ou-se |
📌 Commit 88ccaa7 has been approved by |
@bors retry |
⌛ Testing commit 88ccaa7 with merge 77fee3038ddf4e8e451975a88b57c0f1bd45cdf8... |
💔 Test failed - checks-actions |
@bors retry aarch64-gnu builder no logs |
☀️ Test successful - checks-actions |
Hooray! Thanks everyone. |
This is now available on nightly: https://doc.rust-lang.org/nightly/std/panic/fn.always_abort.html Thanks for working on this, @ijackson! |
Objective scenarios
Command::pre_exec_hook
, including mostpanic!
calls,Option::unwrap
, and array bounds check failures.libc::fork
and then safely panic in the child (needed for the above, but this requirement means exposing the new raw hook API which theCommand
implementation needs).pre_exec_hook
is already memory-safe, prevent the double-unwinding malfunction panic! inCommand
child forked from non-main thread results in exit status 0 #79740.I think we want to make panic after fork safe even though the post-fork child environment is only experienced by users of
unsafe
, beause the subset of Rust in which any panic is UB is really far too hazardous and unnatural.Approach
Command
.Fixes #79740
Rejected (or previously attempted) approaches
'static
. This seems like it would be even more subtle. Also that is a potentially-hot path which I don't want to mess with.String
before calling the hook. This would be a surprising change for existing code and would not be detected by the type system.raw_panic_hook
function to intercept panics in a way that doesn't allocate. (That was an earlier version of this MR.)History
This MR could be considered a v2 of #80263. Thanks to everyone who commented there. In particular, thanks to @m-ou-se, @Mark-Simulacrum and @hyd-dev. (Tagging you since I think you might be interested in this new MR.) Compared to #80263, this MR has very substantial changes and additions.
Additionally, I have recently (2021-04-20) completely revised this series following very helpful comments from @m-ou-se.
r? @m-ou-se