Skip to content

add dtors_in_dtors_in_dtors #2755

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 9, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions tests/pass/concurrency/tls_lib_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}