1 | //! Destructor registration for Linux-like systems. |
2 | //! |
3 | //! Since what appears to be version 2.18, glibc has shipped the |
4 | //! `__cxa_thread_atexit_impl` symbol which GCC and clang both use to invoke |
5 | //! destructors in C++ thread_local globals. This function does exactly what |
6 | //! we want: it schedules a callback which will be run at thread exit with the |
7 | //! provided argument. |
8 | //! |
9 | //! Unfortunately, our minimum supported glibc version (at the time of writing) |
10 | //! is 2.17, so we can only link this symbol weakly and need to use the |
11 | //! [`list`](super::list) destructor implementation as fallback. |
12 | |
13 | use crate::mem::transmute; |
14 | |
15 | pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { |
16 | /// This is necessary because the __cxa_thread_atexit_impl implementation |
17 | /// std links to by default may be a C or C++ implementation that was not |
18 | /// compiled using the Clang integer normalization option. |
19 | #[cfg (sanitizer_cfi_normalize_integers)] |
20 | use core::ffi::c_int; |
21 | #[cfg (not(sanitizer_cfi_normalize_integers))] |
22 | #[cfi_encoding = "i" ] |
23 | #[repr (transparent)] |
24 | #[allow (non_camel_case_types)] |
25 | pub struct c_int(#[allow (dead_code)] pub core::ffi::c_int); |
26 | |
27 | unsafe extern "C" { |
28 | #[linkage = "extern_weak" ] |
29 | static __dso_handle: *mut u8; |
30 | #[linkage = "extern_weak" ] |
31 | static __cxa_thread_atexit_impl: Option< |
32 | extern "C" fn( |
33 | unsafe extern "C" fn(*mut libc::c_void), |
34 | *mut libc::c_void, |
35 | *mut libc::c_void, |
36 | ) -> c_int, |
37 | >; |
38 | } |
39 | |
40 | if let Some(f) = unsafe { __cxa_thread_atexit_impl } { |
41 | unsafe { |
42 | f( |
43 | transmute::<unsafe extern "C" fn(*mut u8), unsafe extern "C" fn(*mut libc::c_void)>( |
44 | dtor, |
45 | ), |
46 | t.cast(), |
47 | (&raw const __dso_handle) as *mut _, |
48 | ); |
49 | } |
50 | } else { |
51 | unsafe { |
52 | super::list::register(t, dtor); |
53 | } |
54 | } |
55 | } |
56 | |