Skip to content

Commit 285ed6b

Browse files
authored
Rollup merge of rust-lang#141248 - RalfJung:reentrant-lock-race, r=joboet
fix data race in ReentrantLock fallback for targets without 64bit atomics See [Zulip](https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/reentrant.20lock.20failure.20on.20musl) for details: the address used to identify a thread might get lazily allocated inside `tls_addr()`, so if we call that *after* doing the `tls_addr.load()` it is too late to establish synchronization with prior threads that used the same address -- the `load()` thus races with the `store()` by that prior thread, and might hence see outdated values, and then the entire logic breaks down. r? `@joboet`
2 parents 9f429e6 + 4a99329 commit 285ed6b

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

std/src/sync/reentrant_lock.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ cfg_if!(
136136
// we only ever read from the tid if `tls_addr` matches the current
137137
// TLS address. In that case, either the tid has been set by
138138
// the current thread, or by a thread that has terminated before
139-
// the current thread was created. In either case, no further
139+
// the current thread's `tls_addr` was allocated. In either case, no further
140140
// synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
141141
tls_addr: Atomic<usize>,
142142
tid: UnsafeCell<u64>,
@@ -154,8 +154,12 @@ cfg_if!(
154154
// NOTE: This assumes that `owner` is the ID of the current
155155
// thread, and may spuriously return `false` if that's not the case.
156156
fn contains(&self, owner: ThreadId) -> bool {
157+
// We must call `tls_addr()` *before* doing the load to ensure that if we reuse an
158+
// earlier thread's address, the `tls_addr.load()` below happens-after everything
159+
// that thread did.
160+
let tls_addr = tls_addr();
157161
// SAFETY: See the comments in the struct definition.
158-
self.tls_addr.load(Ordering::Relaxed) == tls_addr()
162+
self.tls_addr.load(Ordering::Relaxed) == tls_addr
159163
&& unsafe { *self.tid.get() } == owner.as_u64().get()
160164
}
161165

0 commit comments

Comments
 (0)