Skip to content

Commit f1fdd4d

Browse files
committed
Allow the global alloc one TLS slot with a destructor
1 parent 175e043 commit f1fdd4d

File tree

1 file changed

+23
-11
lines changed
  • library/std/src/sys/thread_local/destructors

1 file changed

+23
-11
lines changed

library/std/src/sys/thread_local/destructors/list.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
use crate::cell::RefCell;
1+
use crate::cell::{Cell, RefCell};
22
use crate::sys::thread_local::guard;
33

4+
#[thread_local]
5+
static REENTRANT_DTOR: Cell<Option<(*mut u8, unsafe extern "C" fn(*mut u8))>> = Cell::new(None);
6+
47
#[thread_local]
58
static DTORS: RefCell<Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>> = RefCell::new(Vec::new());
69

710
pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
8-
let Ok(mut dtors) = DTORS.try_borrow_mut() else {
9-
// This point can only be reached if the global allocator calls this
10-
// function again.
11-
// FIXME: maybe use the system allocator instead?
12-
rtabort!("the global allocator may not use TLS with destructors");
13-
};
14-
15-
guard::enable();
16-
17-
dtors.push((t, dtor));
11+
// Borrow DTORS can only fail if the global allocator calls this
12+
// function again.
13+
if let Ok(mut dtors) = DTORS.try_borrow_mut() {
14+
guard::enable();
15+
dtors.push((t, dtor));
16+
} else if REENTRANT_DTOR.get().is_none() {
17+
guard::enable();
18+
REENTRANT_DTOR.set(Some((t, dtor)));
19+
} else {
20+
rtabort!(
21+
"the global allocator may only create one thread-local variable with a destructor"
22+
);
23+
}
1824
}
1925

2026
/// The [`guard`] module contains platform-specific functions which will run this
@@ -41,4 +47,10 @@ pub unsafe fn run() {
4147
}
4248
}
4349
}
50+
51+
if let Some((t, dtor)) = REENTRANT_DTOR.replace(None) {
52+
unsafe {
53+
dtor(t);
54+
}
55+
}
4456
}

0 commit comments

Comments
 (0)