]> git.lizzy.rs Git - rust.git/commitdiff
add dtors_in_dtors_in_dtors
authorRalf Jung <post@ralfj.de>
Mon, 9 Jan 2023 15:35:16 +0000 (16:35 +0100)
committerRalf Jung <post@ralfj.de>
Mon, 9 Jan 2023 15:35:16 +0000 (16:35 +0100)
src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs

index 04e89ec361b74dcc5718e603120f84a51ff2e35f..7ccafec60372d5fbd249d45e06a48abcc25e2d68 100644 (file)
@@ -186,8 +186,65 @@ fn drop(&mut self) {
     }
 }
 
+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();
 }