Skip to content

Commit cb15925

Browse files
committed
Auto merge of rust-lang#2755 - RalfJung:dtors_in_dtors_in_dtors, r=RalfJung
add dtors_in_dtors_in_dtors That's a pretty neat test from the standard library. Sadly not enough to check for rust-lang/miri#2754, but still worth having here.
2 parents d61d359 + 85e87a8 commit cb15925

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs

+57
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,65 @@ fn join_orders_after_tls_destructors() {
186186
}
187187
}
188188

189+
fn dtors_in_dtors_in_dtors() {
190+
use std::cell::UnsafeCell;
191+
use std::sync::{Arc, Condvar, Mutex};
192+
193+
#[derive(Clone, Default)]
194+
struct Signal(Arc<(Mutex<bool>, Condvar)>);
195+
196+
impl Signal {
197+
fn notify(&self) {
198+
let (set, cvar) = &*self.0;
199+
*set.lock().unwrap() = true;
200+
cvar.notify_one();
201+
}
202+
203+
fn wait(&self) {
204+
let (set, cvar) = &*self.0;
205+
let mut set = set.lock().unwrap();
206+
while !*set {
207+
set = cvar.wait(set).unwrap();
208+
}
209+
}
210+
}
211+
212+
struct NotifyOnDrop(Signal);
213+
214+
impl Drop for NotifyOnDrop {
215+
fn drop(&mut self) {
216+
let NotifyOnDrop(ref f) = *self;
217+
f.notify();
218+
}
219+
}
220+
221+
struct S1(Signal);
222+
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
223+
thread_local!(static K2: UnsafeCell<Option<NotifyOnDrop>> = UnsafeCell::new(None));
224+
225+
impl Drop for S1 {
226+
fn drop(&mut self) {
227+
let S1(ref signal) = *self;
228+
unsafe {
229+
let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone())));
230+
}
231+
}
232+
}
233+
234+
let signal = Signal::default();
235+
let signal2 = signal.clone();
236+
let _t = thread::spawn(move || unsafe {
237+
let mut signal = Some(signal2);
238+
K1.with(|s| *s.get() = Some(S1(signal.take().unwrap())));
239+
});
240+
// Note that this test will deadlock if TLS destructors aren't run (this
241+
// requires the destructor to be run to pass the test).
242+
signal.wait();
243+
}
244+
189245
fn main() {
190246
check_destructors();
191247
check_blocking();
192248
join_orders_after_tls_destructors();
249+
dtors_in_dtors_in_dtors();
193250
}

0 commit comments

Comments
 (0)