Skip to content

Commit 655eed3

Browse files
committed
Auto merge of rust-lang#2248 - RalfJung:arc-drop-fix, r=RalfJung
do not protect SRW items This is the Miri version of rust-lang#98017.
2 parents 35023f5 + 1b214a0 commit 655eed3

8 files changed

+102
-89
lines changed

src/stacked_borrows.rs

+7
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,13 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
821821
} else {
822822
Permission::SharedReadWrite
823823
};
824+
let protector = if frozen {
825+
protector
826+
} else {
827+
// We do not protect inside UnsafeCell.
828+
// This fixes https://github.com/rust-lang/rust/issues/55005.
829+
None
830+
};
824831
let item = Item { perm, tag: new_tag, protector };
825832
let mut global = this.machine.stacked_borrows.as_ref().unwrap().borrow_mut();
826833
stacked_borrows.for_each(range, |offset, stack, history| {

tests/fail/stacked_borrows/deallocate_against_barrier2.rs

-17
This file was deleted.

tests/fail/stacked_borrows/deallocate_against_barrier2.stderr

-38
This file was deleted.

tests/pass/0concurrency_arc_drop.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// ignore-windows: Concurrency on Windows is not supported yet.
2+
use std::sync::Arc;
3+
use std::thread;
4+
5+
/// Test for Arc::drop bug (https://github.com/rust-lang/rust/issues/55005)
6+
fn main() {
7+
// The bug seems to take up to 700 iterations to reproduce with most seeds (tested 0-9).
8+
for _ in 0..700 {
9+
let arc_1 = Arc::new(());
10+
let arc_2 = arc_1.clone();
11+
let thread = thread::spawn(|| drop(arc_2));
12+
let mut i = 0;
13+
while i < 256 {
14+
i += 1;
15+
}
16+
drop(arc_1);
17+
thread.join().unwrap();
18+
}
19+
}

tests/pass/0weak_memory_consistency.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ fn test_single_thread() {
217217
}
218218

219219
pub fn main() {
220-
for _ in 0..50 {
220+
for _ in 0..75 {
221221
test_single_thread();
222222
test_mixed_access();
223223
test_load_buffering_acq_rel();

tests/pass/concurrency/sync.rs

+1-32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// ignore-windows: Concurrency on Windows is not supported yet.
2-
// We are making scheduler assumptions here.
3-
// compile-flags: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-preemption-rate=0
2+
// compile-flags: -Zmiri-disable-isolation -Zmiri-strict-provenance
43

54
use std::sync::{Arc, Barrier, Condvar, Mutex, Once, RwLock};
65
use std::thread;
@@ -53,35 +52,6 @@ fn check_conditional_variables_notify_one() {
5352
}
5453
}
5554

56-
fn check_conditional_variables_notify_all() {
57-
let pair = Arc::new(((Mutex::new(())), Condvar::new()));
58-
59-
// Spawn threads and block them on the conditional variable.
60-
let handles: Vec<_> = (0..5)
61-
.map(|_| {
62-
let pair2 = pair.clone();
63-
thread::spawn(move || {
64-
let (lock, cvar) = &*pair2;
65-
let guard = lock.lock().unwrap();
66-
// Block waiting on the conditional variable.
67-
let _ = cvar.wait(guard).unwrap();
68-
})
69-
})
70-
.inspect(|_| {
71-
thread::yield_now();
72-
thread::yield_now();
73-
})
74-
.collect();
75-
76-
let (_, cvar) = &*pair;
77-
// Unblock all threads.
78-
cvar.notify_all();
79-
80-
for handle in handles {
81-
handle.join().unwrap();
82-
}
83-
}
84-
8555
/// Test that waiting on a conditional variable with a timeout does not
8656
/// deadlock.
8757
fn check_conditional_variables_timed_wait_timeout() {
@@ -301,7 +271,6 @@ fn check_condvar() {
301271
fn main() {
302272
check_barriers();
303273
check_conditional_variables_notify_one();
304-
check_conditional_variables_notify_all();
305274
check_conditional_variables_timed_wait_timeout();
306275
check_conditional_variables_timed_wait_notimeout();
307276
check_mutex();
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// ignore-windows: Concurrency on Windows is not supported yet.
2+
// We are making scheduler assumptions here.
3+
// compile-flags: -Zmiri-strict-provenance -Zmiri-preemption-rate=0
4+
5+
use std::sync::{Condvar, Mutex, Arc};
6+
use std::thread;
7+
8+
fn check_conditional_variables_notify_all() {
9+
let pair = Arc::new(((Mutex::new(())), Condvar::new()));
10+
11+
// Spawn threads and block them on the conditional variable.
12+
let handles: Vec<_> = (0..5)
13+
.map(|_| {
14+
let pair2 = pair.clone();
15+
thread::spawn(move || {
16+
let (lock, cvar) = &*pair2;
17+
let guard = lock.lock().unwrap();
18+
// Block waiting on the conditional variable.
19+
let _ = cvar.wait(guard).unwrap();
20+
})
21+
})
22+
.inspect(|_| {
23+
// Ensure the other threads all run and block on the `wait`.
24+
thread::yield_now();
25+
thread::yield_now();
26+
})
27+
.collect();
28+
29+
let (_, cvar) = &*pair;
30+
// Unblock all threads.
31+
cvar.notify_all();
32+
33+
for handle in handles {
34+
handle.join().unwrap();
35+
}
36+
}
37+
38+
fn main() {
39+
check_conditional_variables_notify_all();
40+
}

tests/pass/stacked-borrows/interior_mutability.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
// compile-flags: -Zmiri-tag-raw-pointers
12
use std::cell::{Cell, RefCell, UnsafeCell};
2-
use std::mem::MaybeUninit;
3+
use std::mem::{self, MaybeUninit};
34

45
fn main() {
56
aliasing_mut_and_shr();
67
aliasing_frz_and_shr();
78
into_interior_mutability();
89
unsafe_cell_2phase();
10+
unsafe_cell_deallocate();
11+
unsafe_cell_invalidate();
912
}
1013

1114
fn aliasing_mut_and_shr() {
@@ -67,3 +70,33 @@ fn unsafe_cell_2phase() {
6770
let _val = (*x2.get()).get(0);
6871
}
6972
}
73+
74+
/// Make sure we can deallocate an UnsafeCell that was passed to an active fn call.
75+
/// (This is the fix for https://github.com/rust-lang/rust/issues/55005.)
76+
fn unsafe_cell_deallocate() {
77+
fn f(x: &UnsafeCell<i32>) {
78+
let b: Box<i32> = unsafe { Box::from_raw(x as *const _ as *mut i32) };
79+
drop(b)
80+
}
81+
82+
let b = Box::new(0i32);
83+
f(unsafe { mem::transmute(Box::into_raw(b)) });
84+
}
85+
86+
/// As a side-effect of the above, we also allow this -- at least for now.
87+
fn unsafe_cell_invalidate() {
88+
fn f(_x: &UnsafeCell<i32>, y: *mut i32) {
89+
// Writing to y invalidates x, but that is okay.
90+
unsafe {
91+
*y += 1;
92+
}
93+
}
94+
95+
let mut x = 0i32;
96+
let raw1 = &mut x as *mut _;
97+
let ref1 = unsafe { &mut *raw1 };
98+
let raw2 = ref1 as *mut _;
99+
// Now the borrow stack is: raw1, ref2, raw2.
100+
// So using raw1 invalidates raw2.
101+
f(unsafe { mem::transmute(raw2) }, raw1);
102+
}

0 commit comments

Comments
 (0)