diff options
| author | bors <bors@rust-lang.org> | 2023-01-09 15:36:18 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-01-09 15:36:18 +0000 |
| commit | cb1592518e09098c19d90b4f4f0a8f0373cc1bd5 (patch) | |
| tree | 905fea2b1229e5d9e5ccc18f8bb3597f1a97254d | |
| parent | d61d359d5ef5e3192611297805dbfbb52c55de8f (diff) | |
| parent | 85e87a80fc5b51d395b08ba49adb4242bb751e35 (diff) | |
| download | rust-cb1592518e09098c19d90b4f4f0a8f0373cc1bd5.tar.gz rust-cb1592518e09098c19d90b4f4f0a8f0373cc1bd5.zip | |
Auto merge of #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 https://github.com/rust-lang/miri/issues/2754, but still worth having here.
| -rw-r--r-- | src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs index 04e89ec361b..7ccafec6037 100644 --- a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs +++ b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs @@ -186,8 +186,65 @@ fn join_orders_after_tls_destructors() { } } +fn dtors_in_dtors_in_dtors() { + use std::cell::UnsafeCell; + use std::sync::{Arc, Condvar, Mutex}; + + #[derive(Clone, Default)] + struct Signal(Arc<(Mutex<bool>, Condvar)>); + + impl Signal { + fn notify(&self) { + let (set, cvar) = &*self.0; + *set.lock().unwrap() = true; + cvar.notify_one(); + } + + fn wait(&self) { + let (set, cvar) = &*self.0; + let mut set = set.lock().unwrap(); + while !*set { + set = cvar.wait(set).unwrap(); + } + } + } + + struct NotifyOnDrop(Signal); + + impl Drop for NotifyOnDrop { + fn drop(&mut self) { + let NotifyOnDrop(ref f) = *self; + f.notify(); + } + } + + struct S1(Signal); + thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None)); + thread_local!(static K2: UnsafeCell<Option<NotifyOnDrop>> = UnsafeCell::new(None)); + + impl Drop for S1 { + fn drop(&mut self) { + let S1(ref signal) = *self; + unsafe { + let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone()))); + } + } + } + + let signal = Signal::default(); + let signal2 = signal.clone(); + let _t = thread::spawn(move || unsafe { + let mut signal = Some(signal2); + K1.with(|s| *s.get() = Some(S1(signal.take().unwrap()))); + }); + // Note that this test will deadlock if TLS destructors aren't run (this + // requires the destructor to be run to pass the test). + signal.wait(); +} + fn main() { check_destructors(); check_blocking(); join_orders_after_tls_destructors(); + dtors_in_dtors_in_dtors(); } |
