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::dropimpl 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 aThreadGuardis dropped on the wrong thread, its drop impl will panic, and then the drop glue will attempt to drop thevalue: Tfield before continuing to unwind. This violates the purpose ofThreadGuardas it allows accessing theTon a thread other than the one it was created on (inT'sDropimpl).This PR wraps the
valuefield inManuallyDropso it will not be automatically dropped, and drops it manually inThreadGuard'sDrop::dropimpl 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 thePrintOnDropis 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-seedsruns 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-seedsandrustc 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!indropwhen droppingselfdue 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_innerif that is desired.Footnotes
currently at least, assuming
panic=unwindand notabort, and the thread isn't already panicking, etc ↩