glib: Don't drop T
if ThreadGuard<T>
is dropped on the wrong thread.
#1766
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
When a struct's
Drop::drop
impl panics, Rust will still drop the fields of the struct before continuing to unwind1.glib::thread_guard::ThreadGuard<T>
currently holds avalue: T
, so if aThreadGuard
is dropped on the wrong thread, its drop impl will panic, and then the drop glue will attempt to drop thevalue: T
field before continuing to unwind. This violates the purpose ofThreadGuard
as it allows accessing theT
on a thread other than the one it was created on (inT
'sDrop
impl).This PR wraps the
value
field inManuallyDrop
so it will not be automatically dropped, and drops it manually inThreadGuard
'sDrop::drop
impl if it is on the correct thread.Examples showing issue
The above program prints
ThreadGuard
's panic message, and thendropping value on thread 1 that was produced on thread 0
, showing that thePrintOnDrop
is dropped on a different thread than the one it was created on, despite being in aThreadGuard
.With this PR, the above program no longer prints the message from
PrintOnDrop::drop
.The above program has UB due to racing non-atomic accesses to
Rc
's internal reference counts. (It is somewhat nondeterministic whether Miri will catch the racing, since racing is timing sensitive. Using-Zmiri-many-seeds
runs it several times with different Miri randomization seeds to test different thread interleavings).With this PR, Miri does not detect any UB in the above program (on my machine with
-Zmiri-many-seeds
andrustc 1.90.0-nightly (3014e79f9 2025-07-15)
).Something I noticed that is somewhat unrelated:
ThreadGuard::into_inner
, if called on the wrong thread, will panic twice and thus abort: first in theassert!
ininto_inner
, and second in theassert!
indrop
when droppingself
due to unwinding from the first panic.This is not currently changed by this PR, but could be changed by moving the
let mut this = ManuallyDrop::new(self);
above theassert!
ininto_inner
if that is desired.Footnotes
currently at least, assuming
panic=unwind
and notabort
, and the thread isn't already panicking, etc ↩