about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-09-23 18:13:53 +0200
committerGitHub <noreply@github.com>2025-09-23 18:13:53 +0200
commit64e81e5cb7f8a09e22cd1f570f6a6deb6bda4373 (patch)
tree060c0a717b9513fd83fea6d21fccd07f8da17497
parent8f11c4dadb9e240815ca25e613b17656ab665eda (diff)
parent389a502ade65e82d8a0c4d323118121c1c09c4f8 (diff)
downloadrust-64e81e5cb7f8a09e22cd1f570f6a6deb6bda4373.tar.gz
rust-64e81e5cb7f8a09e22cd1f570f6a6deb6bda4373.zip
Rollup merge of #146799 - cuviper:dangling-count-latch, r=lcnr
Fix a dangling reference in `rustc_thread_pool`

This diverged from `rayon` in rust-lang/rust#142384, where a cleanup commit turned the matched `worker_index` into a reference, which is read _after_ the `set` that may kill it. I've moved that read beforehand, and I hope the new comments will emphasize the subtlety of this unsafe code.

Hopefully fixes rust-lang/rust#146677.
-rw-r--r--compiler/rustc_thread_pool/src/latch.rs8
1 files changed, 6 insertions, 2 deletions
diff --git a/compiler/rustc_thread_pool/src/latch.rs b/compiler/rustc_thread_pool/src/latch.rs
index 18d654d9f78..58dabaf35c0 100644
--- a/compiler/rustc_thread_pool/src/latch.rs
+++ b/compiler/rustc_thread_pool/src/latch.rs
@@ -388,13 +388,17 @@ impl Latch for CountLatch {
     #[inline]
     unsafe fn set(this: *const Self) {
         if unsafe { (*this).counter.fetch_sub(1, Ordering::SeqCst) == 1 } {
-            // NOTE: Once we call `set` on the internal `latch`,
+            // SAFETY: Once we call `set` on the internal `latch`,
             // the target may proceed and invalidate `this`!
             match unsafe { &(*this).kind } {
                 CountLatchKind::Stealing { latch, registry, worker_index } => {
                     let registry = Arc::clone(registry);
+                    let worker_index = *worker_index;
+                    // SAFETY: We don't use any references from `this` after this call.
                     if unsafe { CoreLatch::set(latch) } {
-                        registry.notify_worker_latch_is_set(*worker_index);
+                        // We **must not** access any part of `this` anymore, which
+                        // is why we read and shadowed these fields beforehand.
+                        registry.notify_worker_latch_is_set(worker_index);
                     }
                 }
                 CountLatchKind::Blocking { latch } => unsafe { LockLatch::set(latch) },