| //! macOS allows registering destructors through _tlv_atexit. But since calling | |
| //! it while TLS destructors are running is UB, we still need to keep our own | |
| //! list of destructors. | |
| use crate::cell::Cell; | |
| use crate::ptr; | |
| use crate::sys::thread_local::destructors; | |
| pub fn enable() { | |
| #[thread_local] | |
| static REGISTERED: Cell<bool> = Cell::new(false); | |
| unsafe extern "C" { | |
| fn _tlv_atexit(dtor: unsafe extern "C" fn(*mut u8), arg: *mut u8); | |
| } | |
| if !REGISTERED.replace(true) { | |
| // SAFETY: Calling _tlv_atexit while TLS destructors are running is UB. | |
| // But as run_dtors is only called after being registered, this point | |
| // cannot be reached from it. | |
| unsafe { | |
| _tlv_atexit(run_dtors, ptr::null_mut()); | |
| } | |
| } | |
| unsafe extern "C" fn run_dtors(_: *mut u8) { | |
| unsafe { | |
| destructors::run(); | |
| crate::rt::thread_cleanup(); | |
| } | |
| } | |
| } |