Skip to content
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

Run TLS destructors for main thread on UNIX platforms #133819

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@
#![feature(allow_internal_unstable)]
#![feature(asm_experimental_arch)]
#![feature(cfg_sanitizer_cfi)]
#![feature(cfg_target_has_atomic)]
#![feature(cfg_target_thread_local)]
#![feature(cfi_encoding)]
#![feature(concat_idents)]
Expand Down
40 changes: 33 additions & 7 deletions library/std/src/sys/thread_local/guard/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,38 @@ use crate::sys::thread_local::key::{LazyKey, set};

#[cfg(target_thread_local)]
pub fn enable() {
use crate::sys::thread_local::destructors;
fn enable_thread() {
static DTORS: LazyKey = LazyKey::new(Some(run_thread));

static DTORS: LazyKey = LazyKey::new(Some(run));
// Setting the key value to something other than NULL will result in the
// destructor being run at thread exit.
unsafe {
set(DTORS.force(), ptr::without_provenance_mut(1));
}

unsafe extern "C" fn run_thread(_: *mut u8) {
run()
}
}

#[cfg(target_has_atomic_load_store = "8")]
fn enable_process() {
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sys::thread_local::key::at_process_exit;

// Setting the key value to something other than NULL will result in the
// destructor being run at thread exit.
unsafe {
set(DTORS.force(), ptr::without_provenance_mut(1));
static REGISTERED: AtomicBool = AtomicBool::new(false);
if !REGISTERED.swap(true, Ordering::Relaxed) {
unsafe { at_process_exit(run_process) };
}

unsafe extern "C" fn run_process() {
run()
}
}

unsafe extern "C" fn run(_: *mut u8) {
fn run() {
use crate::sys::thread_local::destructors;

unsafe {
destructors::run();
// On platforms with `__cxa_thread_atexit_impl`, `destructors::run`
Expand All @@ -28,6 +49,11 @@ pub fn enable() {
crate::rt::thread_cleanup();
}
}

enable_thread();

#[cfg(target_has_atomic_load_store = "8")]
enable_process();
}

/// On platforms with key-based TLS, the system runs the destructors for us.
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/thread_local/key/sgx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ pub unsafe fn get(key: Key) -> *mut u8 {
pub unsafe fn destroy(key: Key) {
Tls::destroy(AbiKey::from_usize(key))
}

pub unsafe fn at_process_exit(cb: unsafe extern "C" fn()) {
let _ = cb;
}
10 changes: 10 additions & 0 deletions library/std/src/sys/thread_local/key/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,13 @@ pub unsafe fn destroy(key: Key) {
let r = unsafe { libc::pthread_key_delete(key) };
debug_assert_eq!(r, 0);
}

#[inline]
pub unsafe fn at_process_exit(cb: unsafe extern "C" fn()) {
// Miri does not support atexit.
#[cfg(not(miri))]
assert_eq!(unsafe { libc::atexit(mem::transmute(cb)) }, 0);

#[cfg(miri)]
let _ = cb;
}
4 changes: 2 additions & 2 deletions library/std/src/sys/thread_local/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ pub(crate) mod key {
#[cfg(test)]
mod tests;
pub(super) use racy::LazyKey;
pub(super) use unix::{Key, set};
pub(super) use unix::{Key, set, at_process_exit};
#[cfg(any(not(target_thread_local), test))]
pub(super) use unix::get;
use unix::{create, destroy};
Expand All @@ -156,7 +156,7 @@ pub(crate) mod key {
#[cfg(test)]
mod tests;
pub(super) use racy::LazyKey;
pub(super) use sgx::{Key, get, set};
pub(super) use sgx::{Key, get, set, at_process_exit};
use sgx::{create, destroy};
} else if #[cfg(target_os = "xous")] {
mod racy;
Expand Down
Loading