diff options
| author | Ralf Jung <post@ralfj.de> | 2023-01-09 16:35:16 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2023-01-09 16:35:16 +0100 |
| commit | 85e87a80fc5b51d395b08ba49adb4242bb751e35 (patch) | |
| tree | 905fea2b1229e5d9e5ccc18f8bb3597f1a97254d /src | |
| parent | d61d359d5ef5e3192611297805dbfbb52c55de8f (diff) | |
| download | rust-85e87a80fc5b51d395b08ba49adb4242bb751e35.tar.gz rust-85e87a80fc5b51d395b08ba49adb4242bb751e35.zip | |
add dtors_in_dtors_in_dtors
Diffstat (limited to 'src')
| -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(); } |
