-
Notifications
You must be signed in to change notification settings - Fork 59
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
What to do if the destructor of a pinned field panics? #232
Comments
Yes, or else stack pinning is broken as a whole. Consider a function that pins a variable on the stack but doesn't do anything else unsafe. If the destructor of that variable (or a field of that variable, doesn't matter) panics, the stack frame will still go out of scope as part of unwinding. If some function earlier in the call stack catches the panic (also a safe operation) and then calls more functions, those functions' stack frames can end up using the same memory as the one that went out of scope. |
I created a simplified version with a single pinned field, and ran it though MIRI: As you can see, MIRI gives an error:
I would expect this program to have well-defined behaviour. |
The call to |
Yes. (This was asked before somewhere. We clearly need to improve the docs.) The drop-requirement for pinning is that you must call the destructor. Once the destructor finishes, either by returning or panicking, you may reuse that memory. |
I brought this up for T-lang nomination in rust-lang/rust#71607. |
…akis clarify interaction of pin drop guarantee and panics Cc rust-lang/unsafe-code-guidelines#232 @Diggsey would this have helped?
Fixed by rust-lang/rust#71607. |
288: Run Miri on CI r=taiki-e a=taiki-e The pin guarantees are guarantees of a library, so Miri does not detect violations of the pin API. However, if the generated unsafe code causes UB, Miri may be possible to detect it. Related: rust-lang/miri#823, rust-lang/unsafe-code-guidelines#232 (comment) Co-authored-by: Taiki Endo <te316e89@gmail.com>
Let's say I have an enum, with a variant containing some structurally pinned fields:
Given a
Pin<&mut Foo>
, I would like to do something likemem::replace(pinned_foo, Foo::B)
.Now, in general this would not be allowed, because it would move the pinned fields. However, I should be able to drop the pinned fields in-place, take the unpinned field, and then overwrite the entire value with
Foo::B
.One way of doing this is just using the relevant
ptr::{read, write, drop_in_place}
methods. The problem is that the destructors of the pinned fields might panic, in which case it's unclear what I would need to do to avoid causing UB.Firstly, if the destructor of a pinned field panics, am I allowed to reuse that memory ever? The contract for Pin says that the destructor must run before the memory is reused, but it doesn't say whether it has to complete successfully.
From what I can tell, the optimal method would be to create structs like this:
And then construct instances of it on the stack for each field:
The text was updated successfully, but these errors were encountered: