From cb947bf50bf3e2bd23e0564dfab00e5c2f1e3c9c Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 3 Nov 2026 21:30:24 +0000 Subject: [PATCH] Disable TLS dtors on process::exit Running them may be unsound if called within a drop. --- library/std/src/sys/exit.rs | 2 ++ .../std/src/sys/thread_local/destructors/list.rs | 14 ++++++++++++++ library/std/src/sys/thread_local/mod.rs | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/exit.rs b/library/std/src/sys/exit.rs index 1ca2bd8f6b514..87d48d7fdeb0c 100644 --- a/library/std/src/sys/exit.rs +++ b/library/std/src/sys/exit.rs @@ -92,6 +92,8 @@ cfg_select! { } pub fn exit(code: i32) -> ! { + // Ensure thread local destructors aren't run on any platform. + crate::sys::thread_local::destructors::disable(); cfg_select! { target_os = "hermit" => unsafe { hermit_abi::exit(code) }, target_os = "linux" => unsafe { diff --git a/library/std/src/sys/thread_local/destructors/list.rs b/library/std/src/sys/thread_local/destructors/list.rs index dc767639797fb..2dc075aa1772b 100644 --- a/library/std/src/sys/thread_local/destructors/list.rs +++ b/library/std/src/sys/thread_local/destructors/list.rs @@ -1,11 +1,19 @@ use crate::alloc::System; use crate::cell::RefCell; +use crate::sync::atomic::{Atomic, Ordering}; use crate::sys::thread_local::guard; #[thread_local] static DTORS: RefCell> = RefCell::new(Vec::new_in(System)); +static DISABLE_DTORS: Atomic = Atomic::::new(false); + +/// Permanently disable running TLS dtors. +pub fn disable() { + DISABLE_DTORS.store(true, Ordering::Release); +} + pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { let Ok(mut dtors) = DTORS.try_borrow_mut() else { rtabort!("the System allocator may not use TLS with destructors") @@ -27,6 +35,12 @@ pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { /// May only be run on thread exit to guarantee that there are no live references /// to TLS variables while they are destroyed. pub unsafe fn run() { + if DISABLE_DTORS.load(Ordering::Acquire) { + if let Ok(mut dtors) = DTORS.try_borrow_mut() { + *dtors = Vec::new_in(System); + } + return; + } loop { let mut dtors = DTORS.borrow_mut(); match dtors.pop() { diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index 5d3c23ce04678..add4c83795e20 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -82,12 +82,13 @@ pub(crate) mod destructors { mod linux_like; mod list; pub(super) use linux_like::register; + pub(crate) use list::disable; pub(super) use list::run; } _ => { mod list; pub(super) use list::register; - pub(crate) use list::run; + pub(crate) use list::{disable, run}; } } }