Skip to main content

std/sys/thread_local/destructors/
list.rs

1use crate::alloc::System;
2use crate::cell::RefCell;
3use crate::sys::thread_local::guard;
4
5#[thread_local]
6static DTORS: RefCell<Vec<(*mut u8, unsafe extern "C" fn(*mut u8)), System>> =
7    RefCell::new(Vec::new_in(System));
8
9pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
10    let Ok(mut dtors) = DTORS.try_borrow_mut() else {
11        {
    if let Some(mut out) = crate::sys::stdio::panic_output() {
        let _ =
            crate::io::Write::write_fmt(&mut out,
                format_args!("fatal runtime error: {0}, aborting\n",
                    format_args!("the System allocator may not use TLS with destructors")));
    };
    crate::process::abort();
}rtabort!("the System allocator may not use TLS with destructors")
12    };
13    guard::enable();
14
15    // Avoid calling the alloc error hook
16    if dtors.capacity() == dtors.len() {
17        dtors.try_reserve(1).unwrap_or_else(|_| {
    if let Some(mut out) = crate::sys::stdio::panic_output() {
        let _ =
            crate::io::Write::write_fmt(&mut out,
                format_args!("fatal runtime error: {0}, aborting\n",
                    format_args!("Failed to grow TLS destructor list")));
    };
    crate::process::abort();
}rtabort!("Failed to grow TLS destructor list"))
18    }
19    dtors.push((t, dtor));
20}
21
22/// The [`guard`] module contains platform-specific functions which will run this
23/// function on thread exit if [`guard::enable`] has been called.
24///
25/// # Safety
26///
27/// May only be run on thread exit to guarantee that there are no live references
28/// to TLS variables while they are destroyed.
29pub unsafe fn run() {
30    loop {
31        let mut dtors = DTORS.borrow_mut();
32        match dtors.pop() {
33            Some((t, dtor)) => {
34                drop(dtors);
35                unsafe {
36                    dtor(t);
37                }
38            }
39            None => {
40                // Free the list memory.
41                *dtors = Vec::new_in(System);
42                break;
43            }
44        }
45    }
46}