- Notifications
You must be signed in to change notification settings - Fork 13.9k
Closed
Milestone
Description
The following code sometimes causes a data race to be reported by Miri:
#![feature(atomic_from_mut, inline_const)] use std::sync::atomic::{AtomicBool, Ordering}; fn main() { let mut some_bools = [const { AtomicBool::new(false) }; 10]; let view: &mut [bool] = AtomicBool::get_mut_slice(&mut some_bools); assert_eq!(view, [false; 10]); view[..5].copy_from_slice(&[true; 5]); std::thread::scope(|s| { for t in &some_bools[..5] { s.spawn(move || assert_eq!(t.load(Ordering::Relaxed), true)); } for f in &some_bools[5..] { s.spawn(move || assert_eq!(f.load(Ordering::Relaxed), false)); } }); }
Miri reports:
note: tracking was triggered --> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/thread/scoped.rs:133:17 | 133 | let scope = Scope { | _________________^ 134 | | data: ScopeData { 135 | | num_running_threads: AtomicUsize::new(0), 136 | | main_thread: current(), ... | 140 | | scope: PhantomData, 141 | | }; | |_____^ created allocation with id 1082 | = note: inside `std::thread::scope::<[closure@atomic.rs:12:20: 20:2], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/std/src/thread/scoped.rs:133:17 note: inside `main` at atomic.rs:12:1 --> atomic.rs:12:1 | 12 | / std::thread::scope(|s| { 13 | | for t in &some_bools[..5] { 14 | | s.spawn(move || assert_eq!(t.load(Ordering::Relaxed), true)); 15 | | } ... | 19 | | } 20 | | }); | |__^ error: Undefined Behavior: Data race detected between Deallocate on Thread(id = 0, name = "main") and Read on Thread(id = 2) at alloc1082+0x8 (current vector clock = VClock([114, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]), conflicting timestamp = VClock([113, 0, 9, 9, 9, 0, 0, 0, 0, 0, 9])) --> atomic.rs:12:1 | 12 | / std::thread::scope(|s| { 13 | | for t in &some_bools[..5] { 14 | | s.spawn(move || assert_eq!(t.load(Ordering::Relaxed), true)); 15 | | } ... | 19 | | } 20 | | }); | |__^ Data race detected between Deallocate on Thread(id = 0, name = "main") and Read on Thread(id = 2) at alloc1082+0x8 (current vector clock = VClock([114, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]), conflicting timestamp = VClock([113, 0, 9, 9, 9, 0, 0, 0, 0, 0, 9])) | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: inside `main` at atomic.rs:12:1
The deallocation occurs when scope
returns and its local variable scope
gets deallocated.
The read occurs here (I am fairly sure):
rust/library/std/src/thread/scoped.rs
Lines 58 to 59 in 7098a71
if self.num_running_threads.fetch_sub(1, Ordering::Release) == 1 { | |
self.main_thread.unpark(); |
This reads the contents of the field self.main_thread
after the fetch_sub
. But the moment the fetch_sub
is done, the memory backing self
might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation.
Cc @m-ou-se
bb010g, mcobzarenco and 95th
Metadata
Metadata
Assignees
Labels
No labels