Auto merge of #2646 - saethlin:data-race-spans, r=RalfJung
Data race spans Fixes https://github.com/rust-lang/miri/issues/2205 This adds output to data race errors very similar to the spans we emit for Stacked Borrows errors. For example, from our test suite: ``` help: The Atomic Load on thread `<unnamed>` is here --> tests/fail/data_race/atomic_read_na_write_race1.rs:23:13 | 23 | ... (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between Atomic Load on thread `<unnamed>` and Write o... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: The Write on thread `<unnamed>` is here --> tests/fail/data_race/atomic_read_na_write_race1.rs:19:13 | 19 | *(c.0 as *mut usize) = 32; | ^^^^^^^^^^^^^^^^^^^^^^^^^``` ``` Because of https://github.com/rust-lang/miri/pull/2647 this comes without a perf regression, according to our benchmarks.
This commit is contained in:
commit
245357f619
126 changed files with 554 additions and 272 deletions
|
@ -50,8 +50,10 @@ use rustc_ast::Mutability;
|
|||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_middle::mir;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{Align, Size};
|
||||
|
||||
use crate::diagnostics::RacingOp;
|
||||
use crate::*;
|
||||
|
||||
use super::{
|
||||
|
@ -144,8 +146,8 @@ impl ThreadClockSet {
|
|||
/// Increment the happens-before clock at a
|
||||
/// known index.
|
||||
#[inline]
|
||||
fn increment_clock(&mut self, index: VectorIdx) {
|
||||
self.clock.increment_index(index);
|
||||
fn increment_clock(&mut self, index: VectorIdx, current_span: Span) {
|
||||
self.clock.increment_index(index, current_span);
|
||||
}
|
||||
|
||||
/// Join the happens-before clock with that of
|
||||
|
@ -356,13 +358,9 @@ impl MemoryCellClocks {
|
|||
index: VectorIdx,
|
||||
) -> Result<(), DataRace> {
|
||||
log::trace!("Atomic read with vectors: {:#?} :: {:#?}", self, clocks);
|
||||
if self.write <= clocks.clock[self.write_index] {
|
||||
let atomic = self.atomic_mut();
|
||||
atomic.read_vector.set_at_index(&clocks.clock, index);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DataRace)
|
||||
}
|
||||
if self.write <= clocks.clock[self.write_index] { Ok(()) } else { Err(DataRace) }
|
||||
}
|
||||
|
||||
/// Detect data-races with an atomic write, either with a non-atomic read or with
|
||||
|
@ -373,9 +371,9 @@ impl MemoryCellClocks {
|
|||
index: VectorIdx,
|
||||
) -> Result<(), DataRace> {
|
||||
log::trace!("Atomic write with vectors: {:#?} :: {:#?}", self, clocks);
|
||||
if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
|
||||
let atomic = self.atomic_mut();
|
||||
atomic.write_vector.set_at_index(&clocks.clock, index);
|
||||
if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DataRace)
|
||||
|
@ -386,22 +384,22 @@ impl MemoryCellClocks {
|
|||
/// returns true if a data-race is detected.
|
||||
fn read_race_detect(
|
||||
&mut self,
|
||||
clocks: &ThreadClockSet,
|
||||
clocks: &mut ThreadClockSet,
|
||||
index: VectorIdx,
|
||||
current_span: Span,
|
||||
) -> Result<(), DataRace> {
|
||||
log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, clocks);
|
||||
if !current_span.is_dummy() {
|
||||
clocks.clock[index].span = current_span;
|
||||
}
|
||||
if self.write <= clocks.clock[self.write_index] {
|
||||
let race_free = if let Some(atomic) = self.atomic() {
|
||||
atomic.write_vector <= clocks.clock
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if race_free {
|
||||
self.read.set_at_index(&clocks.clock, index);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DataRace)
|
||||
}
|
||||
if race_free { Ok(()) } else { Err(DataRace) }
|
||||
} else {
|
||||
Err(DataRace)
|
||||
}
|
||||
|
@ -411,21 +409,25 @@ impl MemoryCellClocks {
|
|||
/// returns true if a data-race is detected.
|
||||
fn write_race_detect(
|
||||
&mut self,
|
||||
clocks: &ThreadClockSet,
|
||||
clocks: &mut ThreadClockSet,
|
||||
index: VectorIdx,
|
||||
write_type: WriteType,
|
||||
current_span: Span,
|
||||
) -> Result<(), DataRace> {
|
||||
log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, clocks);
|
||||
if !current_span.is_dummy() {
|
||||
clocks.clock[index].span = current_span;
|
||||
}
|
||||
if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
|
||||
let race_free = if let Some(atomic) = self.atomic() {
|
||||
atomic.write_vector <= clocks.clock && atomic.read_vector <= clocks.clock
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if race_free {
|
||||
self.write = clocks.clock[index];
|
||||
self.write_index = index;
|
||||
self.write_type = write_type;
|
||||
if race_free {
|
||||
self.read.set_zero_vector();
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -621,8 +623,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
|
|||
/// Update the data-race detector for an atomic fence on the current thread.
|
||||
fn atomic_fence(&mut self, atomic: AtomicFenceOrd) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let current_span = this.machine.current_span();
|
||||
if let Some(data_race) = &mut this.machine.data_race {
|
||||
data_race.maybe_perform_sync_operation(&this.machine.threads, |index, mut clocks| {
|
||||
data_race.maybe_perform_sync_operation(
|
||||
&this.machine.threads,
|
||||
current_span,
|
||||
|index, mut clocks| {
|
||||
log::trace!("Atomic fence on {:?} with ordering {:?}", index, atomic);
|
||||
|
||||
// Apply data-race detection for the current fences
|
||||
|
@ -644,7 +650,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
// Increment timestamp in case of release semantics.
|
||||
Ok(atomic != AtomicFenceOrd::Acquire)
|
||||
})
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -682,6 +689,7 @@ impl VClockAlloc {
|
|||
thread_mgr: &ThreadManager<'_, '_>,
|
||||
len: Size,
|
||||
kind: MemoryKind<MiriMemoryKind>,
|
||||
current_span: Span,
|
||||
) -> VClockAlloc {
|
||||
let (alloc_timestamp, alloc_index) = match kind {
|
||||
// User allocated and stack memory should track allocation.
|
||||
|
@ -693,7 +701,8 @@ impl VClockAlloc {
|
|||
)
|
||||
| MemoryKind::Stack => {
|
||||
let (alloc_index, clocks) = global.current_thread_state(thread_mgr);
|
||||
let alloc_timestamp = clocks.clock[alloc_index];
|
||||
let mut alloc_timestamp = clocks.clock[alloc_index];
|
||||
alloc_timestamp.span = current_span;
|
||||
(alloc_timestamp, alloc_index)
|
||||
}
|
||||
// Other global memory should trace races but be allocated at the 0 timestamp.
|
||||
|
@ -704,7 +713,7 @@ impl VClockAlloc {
|
|||
| MiriMemoryKind::ExternStatic
|
||||
| MiriMemoryKind::Tls,
|
||||
)
|
||||
| MemoryKind::CallerLocation => (0, VectorIdx::MAX_INDEX),
|
||||
| MemoryKind::CallerLocation => (VTimestamp::ZERO, VectorIdx::MAX_INDEX),
|
||||
};
|
||||
VClockAlloc {
|
||||
alloc_ranges: RefCell::new(RangeMap::new(
|
||||
|
@ -735,7 +744,7 @@ impl VClockAlloc {
|
|||
let idx = l_remainder_slice
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(idx, &r)| if r == 0 { None } else { Some(idx) })
|
||||
.find_map(|(idx, &r)| if r == VTimestamp::ZERO { None } else { Some(idx) })
|
||||
.expect("Invalid VClock Invariant");
|
||||
Some(idx + r_slice.len())
|
||||
} else {
|
||||
|
@ -762,7 +771,7 @@ impl VClockAlloc {
|
|||
) -> InterpResult<'tcx> {
|
||||
let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
|
||||
let write_clock;
|
||||
let (other_action, other_thread, _other_clock) = if range.write
|
||||
let (other_action, other_thread, other_clock) = if range.write
|
||||
> current_clocks.clock[range.write_index]
|
||||
{
|
||||
// Convert the write action into the vector clock it
|
||||
|
@ -799,14 +808,19 @@ impl VClockAlloc {
|
|||
let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread);
|
||||
|
||||
// Throw the data-race detection.
|
||||
throw_ub_format!(
|
||||
"Data race detected between {} on {} and {} on {} at {:?}",
|
||||
action,
|
||||
current_thread_info,
|
||||
other_action,
|
||||
other_thread_info,
|
||||
ptr_dbg,
|
||||
)
|
||||
Err(err_machine_stop!(TerminationInfo::DataRace {
|
||||
ptr: ptr_dbg,
|
||||
op1: RacingOp {
|
||||
action: other_action.to_string(),
|
||||
thread_info: other_thread_info,
|
||||
span: other_clock.as_slice()[other_thread.index()].span_data(),
|
||||
},
|
||||
op2: RacingOp {
|
||||
action: action.to_string(),
|
||||
thread_info: current_thread_info,
|
||||
span: current_clocks.clock.as_slice()[current_index.index()].span_data(),
|
||||
},
|
||||
}))?
|
||||
}
|
||||
|
||||
/// Detect racing atomic read and writes (not data races)
|
||||
|
@ -840,12 +854,14 @@ impl VClockAlloc {
|
|||
range: AllocRange,
|
||||
machine: &MiriMachine<'_, '_>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let current_span = machine.current_span();
|
||||
let global = machine.data_race.as_ref().unwrap();
|
||||
if global.race_detecting() {
|
||||
let (index, clocks) = global.current_thread_state(&machine.threads);
|
||||
let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
|
||||
let mut alloc_ranges = self.alloc_ranges.borrow_mut();
|
||||
for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
|
||||
if let Err(DataRace) = range.read_race_detect(&clocks, index) {
|
||||
if let Err(DataRace) = range.read_race_detect(&mut clocks, index, current_span) {
|
||||
drop(clocks);
|
||||
// Report data-race.
|
||||
return Self::report_data_race(
|
||||
global,
|
||||
|
@ -871,11 +887,15 @@ impl VClockAlloc {
|
|||
write_type: WriteType,
|
||||
machine: &mut MiriMachine<'_, '_>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let current_span = machine.current_span();
|
||||
let global = machine.data_race.as_mut().unwrap();
|
||||
if global.race_detecting() {
|
||||
let (index, clocks) = global.current_thread_state(&machine.threads);
|
||||
let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
|
||||
for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
|
||||
if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) {
|
||||
if let Err(DataRace) =
|
||||
range.write_race_detect(&mut clocks, index, write_type, current_span)
|
||||
{
|
||||
drop(clocks);
|
||||
// Report data-race
|
||||
return Self::report_data_race(
|
||||
global,
|
||||
|
@ -1100,9 +1120,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
|
|||
size.bytes()
|
||||
);
|
||||
|
||||
let current_span = this.machine.current_span();
|
||||
// Perform the atomic operation.
|
||||
data_race.maybe_perform_sync_operation(
|
||||
&this.machine.threads,
|
||||
current_span,
|
||||
|index, mut clocks| {
|
||||
for (offset, range) in
|
||||
alloc_meta.alloc_ranges.borrow_mut().iter_mut(base_offset, size)
|
||||
|
@ -1303,7 +1325,12 @@ impl GlobalState {
|
|||
// Hook for thread creation, enabled multi-threaded execution and marks
|
||||
// the current thread timestamp as happening-before the current thread.
|
||||
#[inline]
|
||||
pub fn thread_created(&mut self, thread_mgr: &ThreadManager<'_, '_>, thread: ThreadId) {
|
||||
pub fn thread_created(
|
||||
&mut self,
|
||||
thread_mgr: &ThreadManager<'_, '_>,
|
||||
thread: ThreadId,
|
||||
current_span: Span,
|
||||
) {
|
||||
let current_index = self.current_index(thread_mgr);
|
||||
|
||||
// Enable multi-threaded execution, there are now at least two threads
|
||||
|
@ -1320,7 +1347,7 @@ impl GlobalState {
|
|||
// Now re-configure the re-use candidate, increment the clock
|
||||
// for the new sync use of the vector.
|
||||
let vector_clocks = self.vector_clocks.get_mut();
|
||||
vector_clocks[reuse_index].increment_clock(reuse_index);
|
||||
vector_clocks[reuse_index].increment_clock(reuse_index, current_span);
|
||||
|
||||
// Locate the old thread the vector was associated with and update
|
||||
// it to represent the new thread instead.
|
||||
|
@ -1360,8 +1387,8 @@ impl GlobalState {
|
|||
|
||||
// Advance both threads after the synchronized operation.
|
||||
// Both operations are considered to have release semantics.
|
||||
current.increment_clock(current_index);
|
||||
created.increment_clock(created_index);
|
||||
current.increment_clock(current_index, current_span);
|
||||
created.increment_clock(created_index, current_span);
|
||||
}
|
||||
|
||||
/// Hook on a thread join to update the implicit happens-before relation between the joined
|
||||
|
@ -1427,13 +1454,13 @@ impl GlobalState {
|
|||
/// This should be called strictly before any calls to
|
||||
/// `thread_joined`.
|
||||
#[inline]
|
||||
pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>) {
|
||||
pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>, current_span: Span) {
|
||||
let current_index = self.current_index(thread_mgr);
|
||||
|
||||
// Increment the clock to a unique termination timestamp.
|
||||
let vector_clocks = self.vector_clocks.get_mut();
|
||||
let current_clocks = &mut vector_clocks[current_index];
|
||||
current_clocks.increment_clock(current_index);
|
||||
current_clocks.increment_clock(current_index, current_span);
|
||||
|
||||
// Load the current thread id for the executing vector.
|
||||
let vector_info = self.vector_info.get_mut();
|
||||
|
@ -1462,13 +1489,14 @@ impl GlobalState {
|
|||
fn maybe_perform_sync_operation<'tcx>(
|
||||
&self,
|
||||
thread_mgr: &ThreadManager<'_, '_>,
|
||||
current_span: Span,
|
||||
op: impl FnOnce(VectorIdx, RefMut<'_, ThreadClockSet>) -> InterpResult<'tcx, bool>,
|
||||
) -> InterpResult<'tcx> {
|
||||
if self.multi_threaded.get() {
|
||||
let (index, clocks) = self.current_thread_state_mut(thread_mgr);
|
||||
if op(index, clocks)? {
|
||||
let (_, mut clocks) = self.current_thread_state_mut(thread_mgr);
|
||||
clocks.increment_clock(index);
|
||||
clocks.increment_clock(index, current_span);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -1501,10 +1529,10 @@ impl GlobalState {
|
|||
/// since an acquire operation should have occurred before, however
|
||||
/// for futex & condvar operations this is not the case and this
|
||||
/// operation must be used.
|
||||
pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId) {
|
||||
pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId, current_span: Span) {
|
||||
let (index, mut clocks) = self.load_thread_state_mut(thread);
|
||||
lock.clone_from(&clocks.clock);
|
||||
clocks.increment_clock(index);
|
||||
clocks.increment_clock(index, current_span);
|
||||
}
|
||||
|
||||
/// Release a lock handle, express that this happens-before
|
||||
|
@ -1514,10 +1542,15 @@ impl GlobalState {
|
|||
/// For normal locks this should be equivalent to `validate_lock_release`.
|
||||
/// This function only exists for joining over the set of concurrent readers
|
||||
/// in a read-write lock and should not be used for anything else.
|
||||
pub fn validate_lock_release_shared(&self, lock: &mut VClock, thread: ThreadId) {
|
||||
pub fn validate_lock_release_shared(
|
||||
&self,
|
||||
lock: &mut VClock,
|
||||
thread: ThreadId,
|
||||
current_span: Span,
|
||||
) {
|
||||
let (index, mut clocks) = self.load_thread_state_mut(thread);
|
||||
lock.join(&clocks.clock);
|
||||
clocks.increment_clock(index);
|
||||
clocks.increment_clock(index, current_span);
|
||||
}
|
||||
|
||||
/// Load the vector index used by the given thread as well as the set of vector clocks
|
||||
|
|
|
@ -160,6 +160,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let current_thread = this.get_active_thread();
|
||||
let current_span = this.machine.current_span();
|
||||
let init_once = &mut this.machine.threads.sync.init_onces[id];
|
||||
|
||||
assert_eq!(
|
||||
|
@ -172,7 +173,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
// Each complete happens-before the end of the wait
|
||||
if let Some(data_race) = &this.machine.data_race {
|
||||
data_race.validate_lock_release(&mut init_once.data_race, current_thread);
|
||||
data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span);
|
||||
}
|
||||
|
||||
// Wake up everyone.
|
||||
|
@ -188,6 +189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let current_thread = this.get_active_thread();
|
||||
let current_span = this.machine.current_span();
|
||||
let init_once = &mut this.machine.threads.sync.init_onces[id];
|
||||
assert_eq!(
|
||||
init_once.status,
|
||||
|
@ -197,7 +199,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
// Each complete happens-before the end of the wait
|
||||
if let Some(data_race) = &this.machine.data_race {
|
||||
data_race.validate_lock_release(&mut init_once.data_race, current_thread);
|
||||
data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span);
|
||||
}
|
||||
|
||||
// Wake up one waiting thread, so they can go ahead and try to init this.
|
||||
|
|
|
@ -359,6 +359,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
/// return `None`.
|
||||
fn mutex_unlock(&mut self, id: MutexId, expected_owner: ThreadId) -> Option<usize> {
|
||||
let this = self.eval_context_mut();
|
||||
let current_span = this.machine.current_span();
|
||||
let mutex = &mut this.machine.threads.sync.mutexes[id];
|
||||
if let Some(current_owner) = mutex.owner {
|
||||
// Mutex is locked.
|
||||
|
@ -375,7 +376,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// The mutex is completely unlocked. Try transfering ownership
|
||||
// to another thread.
|
||||
if let Some(data_race) = &this.machine.data_race {
|
||||
data_race.validate_lock_release(&mut mutex.data_race, current_owner);
|
||||
data_race.validate_lock_release(
|
||||
&mut mutex.data_race,
|
||||
current_owner,
|
||||
current_span,
|
||||
);
|
||||
}
|
||||
this.mutex_dequeue_and_lock(id);
|
||||
}
|
||||
|
@ -454,6 +459,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
/// Returns `true` if succeeded, `false` if this `reader` did not hold the lock.
|
||||
fn rwlock_reader_unlock(&mut self, id: RwLockId, reader: ThreadId) -> bool {
|
||||
let this = self.eval_context_mut();
|
||||
let current_span = this.machine.current_span();
|
||||
let rwlock = &mut this.machine.threads.sync.rwlocks[id];
|
||||
match rwlock.readers.entry(reader) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
|
@ -470,7 +476,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
Entry::Vacant(_) => return false, // we did not even own this lock
|
||||
}
|
||||
if let Some(data_race) = &this.machine.data_race {
|
||||
data_race.validate_lock_release_shared(&mut rwlock.data_race_reader, reader);
|
||||
data_race.validate_lock_release_shared(
|
||||
&mut rwlock.data_race_reader,
|
||||
reader,
|
||||
current_span,
|
||||
);
|
||||
}
|
||||
|
||||
// The thread was a reader. If the lock is not held any more, give it to a writer.
|
||||
|
@ -511,6 +521,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
#[inline]
|
||||
fn rwlock_writer_unlock(&mut self, id: RwLockId, expected_writer: ThreadId) -> bool {
|
||||
let this = self.eval_context_mut();
|
||||
let current_span = this.machine.current_span();
|
||||
let rwlock = &mut this.machine.threads.sync.rwlocks[id];
|
||||
if let Some(current_writer) = rwlock.writer {
|
||||
if current_writer != expected_writer {
|
||||
|
@ -523,8 +534,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// since this writer happens-before both the union of readers once they are finished
|
||||
// and the next writer
|
||||
if let Some(data_race) = &this.machine.data_race {
|
||||
data_race.validate_lock_release(&mut rwlock.data_race, current_writer);
|
||||
data_race.validate_lock_release(&mut rwlock.data_race_reader, current_writer);
|
||||
data_race.validate_lock_release(
|
||||
&mut rwlock.data_race,
|
||||
current_writer,
|
||||
current_span,
|
||||
);
|
||||
data_race.validate_lock_release(
|
||||
&mut rwlock.data_race_reader,
|
||||
current_writer,
|
||||
current_span,
|
||||
);
|
||||
}
|
||||
// The thread was a writer.
|
||||
//
|
||||
|
@ -595,12 +614,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, CondvarLock)> {
|
||||
let this = self.eval_context_mut();
|
||||
let current_thread = this.get_active_thread();
|
||||
let current_span = this.machine.current_span();
|
||||
let condvar = &mut this.machine.threads.sync.condvars[id];
|
||||
let data_race = &this.machine.data_race;
|
||||
|
||||
// Each condvar signal happens-before the end of the condvar wake
|
||||
if let Some(data_race) = data_race {
|
||||
data_race.validate_lock_release(&mut condvar.data_race, current_thread);
|
||||
data_race.validate_lock_release(&mut condvar.data_race, current_thread, current_span);
|
||||
}
|
||||
condvar.waiters.pop_front().map(|waiter| {
|
||||
if let Some(data_race) = data_race {
|
||||
|
@ -628,12 +648,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
fn futex_wake(&mut self, addr: u64, bitset: u32) -> Option<ThreadId> {
|
||||
let this = self.eval_context_mut();
|
||||
let current_thread = this.get_active_thread();
|
||||
let current_span = this.machine.current_span();
|
||||
let futex = &mut this.machine.threads.sync.futexes.get_mut(&addr)?;
|
||||
let data_race = &this.machine.data_race;
|
||||
|
||||
// Each futex-wake happens-before the end of the futex wait
|
||||
if let Some(data_race) = data_race {
|
||||
data_race.validate_lock_release(&mut futex.data_race, current_thread);
|
||||
data_race.validate_lock_release(&mut futex.data_race, current_thread, current_span);
|
||||
}
|
||||
|
||||
// Wake up the first thread in the queue that matches any of the bits in the bitset.
|
||||
|
|
|
@ -13,6 +13,7 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_middle::mir::Mutability;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::concurrency::data_race;
|
||||
|
@ -617,6 +618,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
|
|||
fn thread_terminated(
|
||||
&mut self,
|
||||
mut data_race: Option<&mut data_race::GlobalState>,
|
||||
current_span: Span,
|
||||
) -> Vec<Pointer<Provenance>> {
|
||||
let mut free_tls_statics = Vec::new();
|
||||
{
|
||||
|
@ -634,7 +636,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
|
|||
}
|
||||
// Set the thread into a terminated state in the data-race detector.
|
||||
if let Some(ref mut data_race) = data_race {
|
||||
data_race.thread_terminated(self);
|
||||
data_race.thread_terminated(self, current_span);
|
||||
}
|
||||
// Check if we need to unblock any threads.
|
||||
let mut joined_threads = vec![]; // store which threads joined, we'll need it
|
||||
|
@ -813,8 +815,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let mut state = tls::TlsDtorsState::default();
|
||||
Box::new(move |m| state.on_stack_empty(m))
|
||||
});
|
||||
let current_span = this.machine.current_span();
|
||||
if let Some(data_race) = &mut this.machine.data_race {
|
||||
data_race.thread_created(&this.machine.threads, new_thread_id);
|
||||
data_race.thread_created(&this.machine.threads, new_thread_id, current_span);
|
||||
}
|
||||
|
||||
// Write the current thread-id, switch to the next thread later
|
||||
|
@ -1041,7 +1044,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
assert!(thread.stack.is_empty(), "only threads with an empty stack can be terminated");
|
||||
thread.state = ThreadState::Terminated;
|
||||
|
||||
for ptr in this.machine.threads.thread_terminated(this.machine.data_race.as_mut()) {
|
||||
let current_span = this.machine.current_span();
|
||||
for ptr in
|
||||
this.machine.threads.thread_terminated(this.machine.data_race.as_mut(), current_span)
|
||||
{
|
||||
this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use rustc_index::vec::Idx;
|
||||
use rustc_span::{Span, SpanData, DUMMY_SP};
|
||||
use smallvec::SmallVec;
|
||||
use std::{cmp::Ordering, fmt::Debug, ops::Index};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
fmt::Debug,
|
||||
ops::{Index, IndexMut},
|
||||
};
|
||||
|
||||
/// A vector clock index, this is associated with a thread id
|
||||
/// but in some cases one vector index may be shared with
|
||||
|
@ -40,9 +45,42 @@ impl From<u32> for VectorIdx {
|
|||
/// clock vectors larger than this will be stored on the heap
|
||||
const SMALL_VECTOR: usize = 4;
|
||||
|
||||
/// The type of the time-stamps recorded in the data-race detector
|
||||
/// set to a type of unsigned integer
|
||||
pub type VTimestamp = u32;
|
||||
/// The time-stamps recorded in the data-race detector consist of both
|
||||
/// a 32-bit unsigned integer which is the actual timestamp, and a `Span`
|
||||
/// so that diagnostics can report what code was responsible for an operation.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct VTimestamp {
|
||||
time: u32,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl VTimestamp {
|
||||
pub const ZERO: VTimestamp = VTimestamp { time: 0, span: DUMMY_SP };
|
||||
|
||||
pub fn span_data(&self) -> SpanData {
|
||||
self.span.data()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for VTimestamp {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.time == other.time
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for VTimestamp {}
|
||||
|
||||
impl PartialOrd for VTimestamp {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for VTimestamp {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.time.cmp(&other.time)
|
||||
}
|
||||
}
|
||||
|
||||
/// A vector clock for detecting data-races, this is conceptually
|
||||
/// a map from a vector index (and thus a thread id) to a timestamp.
|
||||
|
@ -62,7 +100,7 @@ impl VClock {
|
|||
/// for a value at the given index
|
||||
pub fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock {
|
||||
let len = index.index() + 1;
|
||||
let mut vec = smallvec::smallvec![0; len];
|
||||
let mut vec = smallvec::smallvec![VTimestamp::ZERO; len];
|
||||
vec[index.index()] = timestamp;
|
||||
VClock(vec)
|
||||
}
|
||||
|
@ -79,7 +117,7 @@ impl VClock {
|
|||
#[inline]
|
||||
fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] {
|
||||
if self.0.len() < min_len {
|
||||
self.0.resize(min_len, 0);
|
||||
self.0.resize(min_len, VTimestamp::ZERO);
|
||||
}
|
||||
assert!(self.0.len() >= min_len);
|
||||
self.0.as_mut_slice()
|
||||
|
@ -88,11 +126,14 @@ impl VClock {
|
|||
/// Increment the vector clock at a known index
|
||||
/// this will panic if the vector index overflows
|
||||
#[inline]
|
||||
pub fn increment_index(&mut self, idx: VectorIdx) {
|
||||
pub fn increment_index(&mut self, idx: VectorIdx, current_span: Span) {
|
||||
let idx = idx.index();
|
||||
let mut_slice = self.get_mut_with_min_len(idx + 1);
|
||||
let idx_ref = &mut mut_slice[idx];
|
||||
*idx_ref = idx_ref.checked_add(1).expect("Vector clock overflow")
|
||||
idx_ref.time = idx_ref.time.checked_add(1).expect("Vector clock overflow");
|
||||
if !current_span.is_dummy() {
|
||||
idx_ref.span = current_span;
|
||||
}
|
||||
}
|
||||
|
||||
// Join the two vector-clocks together, this
|
||||
|
@ -102,14 +143,23 @@ impl VClock {
|
|||
let rhs_slice = other.as_slice();
|
||||
let lhs_slice = self.get_mut_with_min_len(rhs_slice.len());
|
||||
for (l, &r) in lhs_slice.iter_mut().zip(rhs_slice.iter()) {
|
||||
let l_span = l.span;
|
||||
let r_span = r.span;
|
||||
*l = r.max(*l);
|
||||
l.span = l.span.substitute_dummy(r_span).substitute_dummy(l_span);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the element at the current index of the vector
|
||||
pub fn set_at_index(&mut self, other: &Self, idx: VectorIdx) {
|
||||
let mut_slice = self.get_mut_with_min_len(idx.index() + 1);
|
||||
|
||||
let prev_span = mut_slice[idx.index()].span;
|
||||
|
||||
mut_slice[idx.index()] = other[idx];
|
||||
|
||||
let span = &mut mut_slice[idx.index()].span;
|
||||
*span = span.substitute_dummy(prev_span);
|
||||
}
|
||||
|
||||
/// Set the vector to the all-zero vector
|
||||
|
@ -313,7 +363,14 @@ impl Index<VectorIdx> for VClock {
|
|||
|
||||
#[inline]
|
||||
fn index(&self, index: VectorIdx) -> &VTimestamp {
|
||||
self.as_slice().get(index.to_u32() as usize).unwrap_or(&0)
|
||||
self.as_slice().get(index.to_u32() as usize).unwrap_or(&VTimestamp::ZERO)
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<VectorIdx> for VClock {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: VectorIdx) -> &mut VTimestamp {
|
||||
self.0.as_mut_slice().get_mut(index.to_u32() as usize).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,6 +381,7 @@ impl Index<VectorIdx> for VClock {
|
|||
mod tests {
|
||||
|
||||
use super::{VClock, VTimestamp, VectorIdx};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[test]
|
||||
|
@ -331,13 +389,13 @@ mod tests {
|
|||
let mut c1 = VClock::default();
|
||||
let mut c2 = VClock::default();
|
||||
assert_eq!(c1, c2);
|
||||
c1.increment_index(VectorIdx(5));
|
||||
c1.increment_index(VectorIdx(5), DUMMY_SP);
|
||||
assert_ne!(c1, c2);
|
||||
c2.increment_index(VectorIdx(53));
|
||||
c2.increment_index(VectorIdx(53), DUMMY_SP);
|
||||
assert_ne!(c1, c2);
|
||||
c1.increment_index(VectorIdx(53));
|
||||
c1.increment_index(VectorIdx(53), DUMMY_SP);
|
||||
assert_ne!(c1, c2);
|
||||
c2.increment_index(VectorIdx(5));
|
||||
c2.increment_index(VectorIdx(5), DUMMY_SP);
|
||||
assert_eq!(c1, c2);
|
||||
}
|
||||
|
||||
|
@ -386,14 +444,14 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
fn from_slice(mut slice: &[VTimestamp]) -> VClock {
|
||||
fn from_slice(mut slice: &[u32]) -> VClock {
|
||||
while let Some(0) = slice.last() {
|
||||
slice = &slice[..slice.len() - 1]
|
||||
}
|
||||
VClock(smallvec::SmallVec::from_slice(slice))
|
||||
VClock(slice.iter().copied().map(|time| VTimestamp { time, span: DUMMY_SP }).collect())
|
||||
}
|
||||
|
||||
fn assert_order(l: &[VTimestamp], r: &[VTimestamp], o: Option<Ordering>) {
|
||||
fn assert_order(l: &[u32], r: &[u32], o: Option<Ordering>) {
|
||||
let l = from_slice(l);
|
||||
let r = from_slice(r);
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
|
|||
// The thread index and timestamp of the initialisation write
|
||||
// are never meaningfully used, so it's fine to leave them as 0
|
||||
store_index: VectorIdx::from(0),
|
||||
timestamp: 0,
|
||||
timestamp: VTimestamp::ZERO,
|
||||
val: init,
|
||||
is_seqcst: false,
|
||||
load_info: RefCell::new(LoadInfo::default()),
|
||||
|
|
|
@ -35,6 +35,17 @@ pub enum TerminationInfo {
|
|||
link_name: Symbol,
|
||||
span: SpanData,
|
||||
},
|
||||
DataRace {
|
||||
op1: RacingOp,
|
||||
op2: RacingOp,
|
||||
ptr: Pointer,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct RacingOp {
|
||||
pub action: String,
|
||||
pub thread_info: String,
|
||||
pub span: SpanData,
|
||||
}
|
||||
|
||||
impl fmt::Display for TerminationInfo {
|
||||
|
@ -55,6 +66,12 @@ impl fmt::Display for TerminationInfo {
|
|||
write!(f, "multiple definitions of symbol `{link_name}`"),
|
||||
SymbolShimClashing { link_name, .. } =>
|
||||
write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",),
|
||||
DataRace { ptr, op1, op2 } =>
|
||||
write!(
|
||||
f,
|
||||
"Data race detected between (1) {} on {} and (2) {} on {} at {ptr:?}. (2) just happened here",
|
||||
op1.action, op1.thread_info, op2.action, op2.thread_info
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +184,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||
Abort(_) => Some("abnormal termination"),
|
||||
UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance =>
|
||||
Some("unsupported operation"),
|
||||
StackedBorrowsUb { .. } => Some("Undefined Behavior"),
|
||||
StackedBorrowsUb { .. } | DataRace { .. } => Some("Undefined Behavior"),
|
||||
Deadlock => Some("deadlock"),
|
||||
MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None,
|
||||
};
|
||||
|
@ -205,6 +222,12 @@ pub fn report_error<'tcx, 'mir>(
|
|||
vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))],
|
||||
Int2PtrWithStrictProvenance =>
|
||||
vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))],
|
||||
DataRace { op1, .. } =>
|
||||
vec![
|
||||
(Some(op1.span), format!("and (1) occurred earlier here")),
|
||||
(None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
|
||||
(None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
|
||||
],
|
||||
_ => vec![],
|
||||
};
|
||||
(title, helps)
|
||||
|
@ -339,9 +362,11 @@ fn report_msg<'tcx>(
|
|||
}
|
||||
|
||||
// Show note and help messages.
|
||||
let mut extra_span = false;
|
||||
for (span_data, note) in ¬es {
|
||||
if let Some(span_data) = span_data {
|
||||
err.span_note(span_data.span(), note);
|
||||
extra_span = true;
|
||||
} else {
|
||||
err.note(note);
|
||||
}
|
||||
|
@ -349,13 +374,14 @@ fn report_msg<'tcx>(
|
|||
for (span_data, help) in &helps {
|
||||
if let Some(span_data) = span_data {
|
||||
err.span_help(span_data.span(), help);
|
||||
extra_span = true;
|
||||
} else {
|
||||
err.help(help);
|
||||
}
|
||||
}
|
||||
if notes.len() + helps.len() > 0 {
|
||||
// Add visual separator before backtrace.
|
||||
err.note("BACKTRACE:");
|
||||
err.note(if extra_span { "BACKTRACE (of the first span):" } else { "BACKTRACE:" });
|
||||
}
|
||||
// Add backtrace
|
||||
for (idx, frame_info) in stacktrace.iter().enumerate() {
|
||||
|
|
|
@ -956,6 +956,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||
&ecx.machine.threads,
|
||||
alloc.size(),
|
||||
kind,
|
||||
ecx.machine.current_span(),
|
||||
)
|
||||
});
|
||||
let buffer_alloc = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation);
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a Unique retag
|
|||
|
|
||||
LL | let res = helper(val, ptr);
|
||||
| ^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `helper` at $DIR/box-cell-alias.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/box-cell-alias.rs:LL:CC
|
||||
|
|
|
@ -37,7 +37,7 @@ pub fn main() {
|
|||
let pointer = &*ptr.0;
|
||||
|
||||
// Note: could also error due to reading uninitialized memory, but the data-race detector triggers first.
|
||||
*pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>`
|
||||
*pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/alloc_read_race.rs:LL:CC
|
||||
|
|
||||
LL | *pointer.load(Ordering::Relaxed)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/alloc_read_race.rs:LL:CC
|
||||
|
|
||||
LL | pointer.store(Box::into_raw(Box::new_uninit()), Ordering::Relaxed);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/alloc_read_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -35,7 +35,7 @@ pub fn main() {
|
|||
|
||||
let j2 = spawn(move || {
|
||||
let pointer = &*ptr.0;
|
||||
*pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>`
|
||||
*pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/alloc_write_race.rs:LL:CC
|
||||
|
|
||||
LL | *pointer.load(Ordering::Relaxed) = 2;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/alloc_write_race.rs:LL:CC
|
||||
|
|
||||
LL | .store(Box::into_raw(Box::<usize>::new_uninit()) as *mut usize, Ordering::Relaxed);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/alloc_write_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn main() {
|
|||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
(&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
(&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/atomic_read_na_write_race1.rs:LL:CC
|
||||
|
|
||||
LL | (&*c.0).load(Ordering::SeqCst)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/atomic_read_na_write_race1.rs:LL:CC
|
||||
|
|
||||
LL | *(c.0 as *mut usize) = 32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/atomic_read_na_write_race1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -23,7 +23,7 @@ pub fn main() {
|
|||
|
||||
let j2 = spawn(move || {
|
||||
let atomic_ref = &mut *c.0;
|
||||
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>`
|
||||
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/atomic_read_na_write_race2.rs:LL:CC
|
||||
|
|
||||
LL | *atomic_ref.get_mut() = 32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/atomic_read_na_write_race2.rs:LL:CC
|
||||
|
|
||||
LL | atomic_ref.load(Ordering::SeqCst)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/atomic_read_na_write_race2.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -23,7 +23,7 @@ pub fn main() {
|
|||
|
||||
let j2 = spawn(move || {
|
||||
let atomic_ref = &mut *c.0;
|
||||
*atomic_ref.get_mut() //~ ERROR: Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>`
|
||||
*atomic_ref.get_mut() //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/atomic_write_na_read_race1.rs:LL:CC
|
||||
|
|
||||
LL | *atomic_ref.get_mut()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/atomic_write_na_read_race1.rs:LL:CC
|
||||
|
|
||||
LL | atomic_ref.store(32, Ordering::SeqCst)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/atomic_write_na_read_race1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn main() {
|
|||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
(&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>`
|
||||
(&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/atomic_write_na_read_race2.rs:LL:CC
|
||||
|
|
||||
LL | (&*c.0).store(32, Ordering::SeqCst);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/atomic_write_na_read_race2.rs:LL:CC
|
||||
|
|
||||
LL | let _val = *(c.0 as *mut usize);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/atomic_write_na_read_race2.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn main() {
|
|||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
(&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
(&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/atomic_write_na_write_race1.rs:LL:CC
|
||||
|
|
||||
LL | (&*c.0).store(64, Ordering::SeqCst);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/atomic_write_na_write_race1.rs:LL:CC
|
||||
|
|
||||
LL | *(c.0 as *mut usize) = 32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/atomic_write_na_write_race1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -23,7 +23,7 @@ pub fn main() {
|
|||
|
||||
let j2 = spawn(move || {
|
||||
let atomic_ref = &mut *c.0;
|
||||
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>`
|
||||
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/atomic_write_na_write_race2.rs:LL:CC
|
||||
|
|
||||
LL | *atomic_ref.get_mut() = 32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/atomic_write_na_write_race2.rs:LL:CC
|
||||
|
|
||||
LL | atomic_ref.store(64, Ordering::SeqCst);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/atomic_write_na_write_race2.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -34,7 +34,7 @@ fn main() {
|
|||
|
||||
let join2 = unsafe {
|
||||
spawn(move || {
|
||||
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
})
|
||||
};
|
||||
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/dangling_thread_async_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 64;
|
||||
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/dangling_thread_async_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 32;
|
||||
| ^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/dangling_thread_async_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -33,6 +33,6 @@ fn main() {
|
|||
spawn(|| ()).join().unwrap();
|
||||
|
||||
unsafe {
|
||||
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `main` and Write on thread `<unnamed>`
|
||||
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
|
||||
--> $DIR/dangling_thread_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 64;
|
||||
| ^^^^^^^^^ Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/dangling_thread_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 32;
|
||||
| ^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/dangling_thread_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -25,7 +25,7 @@ pub fn main() {
|
|||
|
||||
let j2 = spawn(move || {
|
||||
__rust_dealloc(
|
||||
//~^ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>`
|
||||
//~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
|
||||
ptr.0 as *mut _,
|
||||
std::mem::size_of::<usize>(),
|
||||
std::mem::align_of::<usize>(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/dealloc_read_race1.rs:LL:CC
|
||||
|
|
||||
LL | / __rust_dealloc(
|
||||
|
@ -7,11 +7,16 @@ LL | | ptr.0 as *mut _,
|
|||
LL | | std::mem::size_of::<usize>(),
|
||||
LL | | std::mem::align_of::<usize>(),
|
||||
LL | | );
|
||||
| |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
||||
| |_____________^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/dealloc_read_race1.rs:LL:CC
|
||||
|
|
||||
LL | let _val = *ptr.0;
|
||||
| ^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/dealloc_read_race1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -28,7 +28,7 @@ pub fn main() {
|
|||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
// Also an error of the form: Data race detected between Read on thread `<unnamed>` and Deallocate on thread `<unnamed>`
|
||||
// Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
|
||||
// but the invalid allocation is detected first.
|
||||
*ptr.0 //~ ERROR: dereferenced after this allocation got freed
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@ pub fn main() {
|
|||
sleep(Duration::from_millis(200));
|
||||
|
||||
// Now `stack_var` gets deallocated.
|
||||
} //~ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>`
|
||||
} //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
|
||||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/dealloc_read_race_stack.rs:LL:CC
|
||||
|
|
||||
LL | }
|
||||
| ^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
||||
| ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/dealloc_read_race_stack.rs:LL:CC
|
||||
|
|
||||
LL | *pointer.load(Ordering::Acquire)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/dealloc_read_race_stack.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -24,7 +24,7 @@ pub fn main() {
|
|||
|
||||
let j2 = spawn(move || {
|
||||
__rust_dealloc(
|
||||
//~^ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
//~^ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
|
||||
ptr.0 as *mut _,
|
||||
std::mem::size_of::<usize>(),
|
||||
std::mem::align_of::<usize>(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/dealloc_write_race1.rs:LL:CC
|
||||
|
|
||||
LL | / __rust_dealloc(
|
||||
|
@ -7,11 +7,16 @@ LL | | ptr.0 as *mut _,
|
|||
LL | | std::mem::size_of::<usize>(),
|
||||
LL | | std::mem::align_of::<usize>(),
|
||||
LL | | );
|
||||
| |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| |_____________^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/dealloc_write_race1.rs:LL:CC
|
||||
|
|
||||
LL | *ptr.0 = 2;
|
||||
| ^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/dealloc_write_race1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -27,7 +27,7 @@ pub fn main() {
|
|||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
// Also an error of the form: Data race detected between Write on thread `<unnamed>` and Deallocate on thread `<unnamed>`
|
||||
// Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
// but the invalid allocation is detected first.
|
||||
*ptr.0 = 2; //~ ERROR: dereferenced after this allocation got freed
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@ pub fn main() {
|
|||
sleep(Duration::from_millis(200));
|
||||
|
||||
// Now `stack_var` gets deallocated.
|
||||
} //~ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
} //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
|
||||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/dealloc_write_race_stack.rs:LL:CC
|
||||
|
|
||||
LL | }
|
||||
| ^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/dealloc_write_race_stack.rs:LL:CC
|
||||
|
|
||||
LL | *pointer.load(Ordering::Acquire) = 3;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/dealloc_write_race_stack.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -30,7 +30,7 @@ pub fn main() {
|
|||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/enable_after_join_to_main.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 64;
|
||||
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/enable_after_join_to_main.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 32;
|
||||
| ^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/enable_after_join_to_main.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -20,5 +20,5 @@ fn main() {
|
|||
// The fence is useless, since it did not happen-after the `store` in the other thread.
|
||||
// Hence this is a data race.
|
||||
// Also see https://github.com/rust-lang/miri/issues/2192.
|
||||
unsafe { V = 2 } //~ERROR: Data race detected between Write on thread `main` and Write on thread `<unnamed>`
|
||||
unsafe { V = 2 } //~ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
|
||||
--> $DIR/fence_after_load.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { V = 2 }
|
||||
| ^^^^^ Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/fence_after_load.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { V = 1 }
|
||||
| ^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/fence_after_load.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ pub fn main() {
|
|||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>`
|
||||
*c.0 = 64; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/read_write_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 64;
|
||||
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/read_write_race.rs:LL:CC
|
||||
|
|
||||
LL | let _val = *c.0;
|
||||
| ^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/read_write_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -42,7 +42,7 @@ pub fn main() {
|
|||
|
||||
sleep(Duration::from_millis(200));
|
||||
|
||||
stack_var //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
stack_var //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
|
||||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/read_write_race_stack.rs:LL:CC
|
||||
|
|
||||
LL | stack_var
|
||||
| ^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/read_write_race_stack.rs:LL:CC
|
||||
|
|
||||
LL | *pointer.load(Ordering::Acquire) = 3;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/read_write_race_stack.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -37,7 +37,7 @@ pub fn main() {
|
|||
|
||||
let j3 = spawn(move || {
|
||||
if SYNC.load(Ordering::Acquire) == 2 {
|
||||
*c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/relax_acquire_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0
|
||||
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/relax_acquire_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 1;
|
||||
| ^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/relax_acquire_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -41,7 +41,7 @@ pub fn main() {
|
|||
let j3 = spawn(move || {
|
||||
sleep(Duration::from_millis(500));
|
||||
if SYNC.load(Ordering::Acquire) == 3 {
|
||||
*c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/release_seq_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0
|
||||
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/release_seq_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 1;
|
||||
| ^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/release_seq_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -37,7 +37,7 @@ pub fn main() {
|
|||
|
||||
let j2 = spawn(move || {
|
||||
if SYNC.load(Ordering::Acquire) == 2 {
|
||||
*c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/release_seq_race_same_thread.rs:LL:CC
|
||||
|
|
||||
LL | *c.0
|
||||
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/release_seq_race_same_thread.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 1;
|
||||
| ^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/release_seq_race_same_thread.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -38,7 +38,7 @@ pub fn main() {
|
|||
|
||||
let j3 = spawn(move || {
|
||||
if SYNC.load(Ordering::Acquire) == 3 {
|
||||
*c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/rmw_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0
|
||||
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/rmw_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 1;
|
||||
| ^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/rmw_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -21,4 +21,4 @@ fn race(local: i32) {
|
|||
// Deallocating the local (when `main` returns)
|
||||
// races with the read in the other thread.
|
||||
// Make sure the error points at this function's end, not just the call site.
|
||||
} //~ERROR: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>`
|
||||
} //~ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main`
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
|
||||
--> $DIR/stack_pop_race.rs:LL:CC
|
||||
|
|
||||
LL | }
|
||||
| ^ Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
|
||||
| ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/stack_pop_race.rs:LL:CC
|
||||
|
|
||||
LL | let _val = unsafe { *ptr.0 };
|
||||
| ^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `race` at $DIR/stack_pop_race.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/stack_pop_race.rs:LL:CC
|
||||
|
|
|
@ -19,7 +19,7 @@ pub fn main() {
|
|||
});
|
||||
|
||||
let j2 = spawn(move || {
|
||||
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
});
|
||||
|
||||
j1.join().unwrap();
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/write_write_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 64;
|
||||
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/write_write_race.rs:LL:CC
|
||||
|
|
||||
LL | *c.0 = 32;
|
||||
| ^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/write_write_race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -39,7 +39,7 @@ pub fn main() {
|
|||
|
||||
sleep(Duration::from_millis(200));
|
||||
|
||||
stack_var = 1usize; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
|
||||
stack_var = 1usize; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
|
||||
|
||||
// read to silence errors
|
||||
stack_var
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/write_write_race_stack.rs:LL:CC
|
||||
|
|
||||
LL | stack_var = 1usize;
|
||||
| ^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
|
||||
| ^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/write_write_race_stack.rs:LL:CC
|
||||
|
|
||||
LL | *pointer.load(Ordering::Acquire) = 3;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/write_write_race_stack.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -14,7 +14,7 @@ help: then it's defined here again, in crate `exported_symbol_clashing`
|
|||
|
|
||||
LL | fn bar() {}
|
||||
| ^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/exported_symbol_clashing.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -12,7 +12,7 @@ LL | |
|
|||
LL | | unreachable!()
|
||||
LL | | }
|
||||
| |_^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/exported_symbol_shim_clashing.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | *target = 13;
|
||||
| ^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/alias_through_mutation.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> is this argument
|
|||
|
|
||||
LL | pub fn safe(_x: &mut i32, _y: &mut i32) {}
|
||||
| ^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/aliasing_mut1.rs:LL:CC
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> is this argument
|
|||
|
|
||||
LL | pub fn safe(_x: &i32, _y: &mut i32) {}
|
||||
| ^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/aliasing_mut2.rs:LL:CC
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry reta
|
|||
|
|
||||
LL | safe_raw(xraw, xshr);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/aliasing_mut3.rs:LL:CC
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> is this argument
|
|||
|
|
||||
LL | pub fn safe(_x: &i32, _y: &mut Cell<i32>) {}
|
||||
| ^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `safe` at $DIR/aliasing_mut4.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/aliasing_mut4.rs:LL:CC
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | *our = 5;
|
||||
| ^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `unknown_code_2` at $DIR/box_exclusive_violation1.rs:LL:CC
|
||||
note: inside `demo_box_advanced_unique`
|
||||
--> $DIR/box_exclusive_violation1.rs:LL:CC
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> is this argument
|
|||
|
|
||||
LL | unsafe fn test(mut x: Box<i32>, y: *const i32) -> i32 {
|
||||
| ^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `test` at $DIR/box_noalias_violation.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/box_noalias_violation.rs:LL:CC
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique retag
|
|||
|
|
||||
LL | unsafe { from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len()) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/buggy_as_mut_slice.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x10] by a Unique retag
|
|||
|
|
||||
LL | from_raw_parts_mut(ptr.offset(mid as isize), len - mid),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/buggy_split_at_mut.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | *base = 1;
|
||||
| ^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/disable_mut_does_not_merge_srw.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry reta
|
|||
|
|
||||
LL | x.do_bad();
|
||||
| ^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/fnentry_invalidation.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique FnEntry reta
|
|||
|
|
||||
LL | let _ = t.sli.as_mut_ptr();
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/fnentry_invalidation2.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a write access
|
|||
|
|
||||
LL | ptr1.write(0);
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/illegal_deALLOC.rs:LL:CC
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
|||
|
|
||||
LL | let _val = unsafe { *xraw };
|
||||
| ^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a SharedReadOnly reta
|
|||
|
|
||||
LL | let shr = unsafe { &*xraw };
|
||||
| ^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read2.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
|||
|
|
||||
LL | let _val = unsafe { *xref1.r };
|
||||
| ^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read3.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
|||
|
|
||||
LL | let _val = unsafe { *xraw }; // use the raw again, this invalidates xref2 *even* with the special read except for uniq refs
|
||||
| ^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read4.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [$HEX..$HEX] by a read access
|
|||
|
|
||||
LL | mem::forget(unsafe { ptr::read(xshr) }); // but after reading through the shared ref
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read5.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
|
|||
|
|
||||
LL | let x = &mut *x; // kill `raw`
|
||||
| ^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read6.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
|||
|
|
||||
LL | let _val = ptr::read(raw);
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read7.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | *y2 += 1;
|
||||
| ^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read8.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | *exposed_ptr = 0;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read_despite_exposed1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
|||
|
|
||||
LL | let _val = *exposed_ptr;
|
||||
| ^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_read_despite_exposed2.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
|
|||
|
|
||||
LL | let x: *mut u32 = xref as *const _ as *mut _;
|
||||
| ^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_write1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
|
|||
|
|
||||
LL | drop(&mut *target); // reborrow
|
||||
| ^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_write2.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
|
|||
|
|
||||
LL | let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag
|
||||
| ^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_write3.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
|
|||
|
|
||||
LL | let _mut_ref: &mut i32 = unsafe { mem::transmute(raw) }; // &mut, with raw tag
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_write4.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | unsafe { *xraw = 15 };
|
||||
| ^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_write5.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> is this argument
|
|||
|
|
||||
LL | fn foo(a: &mut u32, y: *mut u32) -> u32 {
|
||||
| ^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `foo` at $DIR/illegal_write6.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/illegal_write6.rs:LL:CC
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | *exposed_ptr = 0;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/illegal_write_despite_exposed1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | *c.get() = UnsafeCell::new(1); // invalidates inner_shr
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/interior_mut1.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | *c.get() = UnsafeCell::new(0); // now inner_shr gets invalidated
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/interior_mut2.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> is this argument
|
|||
|
|
||||
LL | fn inner(x: *mut i32, _y: &mut i32) {
|
||||
| ^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `inner` at $DIR/invalidate_against_protector1.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/invalidate_against_protector1.rs:LL:CC
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> is this argument
|
|||
|
|
||||
LL | fn inner(x: *mut i32, _y: &i32) {
|
||||
| ^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `inner` at $DIR/invalidate_against_protector2.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/invalidate_against_protector2.rs:LL:CC
|
||||
|
|
|
@ -16,7 +16,7 @@ help: <TAG> is this argument
|
|||
|
|
||||
LL | fn inner(x: *mut i32, _y: &i32) {
|
||||
| ^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `inner` at $DIR/invalidate_against_protector3.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/invalidate_against_protector3.rs:LL:CC
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
|||
|
|
||||
LL | let _val = unsafe { *xraw }; // invalidate xref
|
||||
| ^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/load_invalid_mut.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
|
@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
|||
|
|
||||
LL | unsafe { *xraw = 42 }; // unfreeze
|
||||
| ^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `main` at $DIR/load_invalid_shr.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue