Skip to content

Commit efaf4e0

Browse files
committed
Auto merge of rust-lang#139996 - matthiaskrgr:rollup-0nka2hw, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#138528 (deref patterns: implement implicit deref patterns) - rust-lang#139393 (rustdoc-json: Output target feature information) - rust-lang#139553 (sync::mpsc: prevent double free on `Drop`) - rust-lang#139615 (Remove `name_or_empty`) - rust-lang#139853 (Disable combining LLD with external llvm-config) - rust-lang#139913 (rustdoc/clean: Fix lowering of fn params (fixes correctness & HIR vs. middle parity regressions)) - rust-lang#139942 (Ignore aix for tests/ui/erros/pic-linker.rs) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 4b57af8 + ee51ea6 commit efaf4e0

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

Diff for: std/src/sync/mpmc/list.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ impl<T> Channel<T> {
213213
.compare_exchange(block, new, Ordering::Release, Ordering::Relaxed)
214214
.is_ok()
215215
{
216+
// This yield point leaves the channel in a half-initialized state where the
217+
// tail.block pointer is set but the head.block is not. This is used to
218+
// facilitate the test in src/tools/miri/tests/pass/issues/issue-139553.rs
219+
#[cfg(miri)]
220+
crate::thread::yield_now();
216221
self.head.block.store(new, Ordering::Release);
217222
block = new;
218223
} else {
@@ -564,9 +569,15 @@ impl<T> Channel<T> {
564569
// In that case, just wait until it gets initialized.
565570
while block.is_null() {
566571
backoff.spin_heavy();
567-
block = self.head.block.load(Ordering::Acquire);
572+
block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel);
568573
}
569574
}
575+
// After this point `head.block` is not modified again and it will be deallocated if it's
576+
// non-null. The `Drop` code of the channel, which runs after this function, also attempts
577+
// to deallocate `head.block` if it's non-null. Therefore this function must maintain the
578+
// invariant that if a deallocation of head.block is attemped then it must also be set to
579+
// NULL. Failing to do so will lead to the Drop code attempting a double free. For this
580+
// reason both reads above do an atomic swap instead of a simple atomic load.
570581

571582
unsafe {
572583
// Drop all messages between head and tail and deallocate the heap-allocated blocks.

0 commit comments

Comments
 (0)