std: abort the process on failure to allocate a TLS key
The panic machinery uses TLS, so panicking if no TLS keys are left can lead to infinite recursion (see https://github.com/rust-lang/rust/issues/140798#issuecomment-2872307377). Rather than having separate logic for the panic count and the thread name, just always abort the process if a TLS key allocation fails. This also has the benefit of aligning the key-based TLS implementation with the documentation, which does not mention that a panic could also occur because of resource exhaustion.
diff --git a/library/std/src/sys/thread_local/key/unix.rs b/library/std/src/sys/thread_local/key/unix.rs
index 93bd0d1..8fa2426 100644
--- a/library/std/src/sys/thread_local/key/unix.rs
+++ b/library/std/src/sys/thread_local/key/unix.rs
@@ -25,7 +25,9 @@ pub fn pthread_key_create(
#[inline]
pub fn create(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
let mut key = 0;
- assert_eq!(unsafe { libc::pthread_key_create(&mut key, mem::transmute(dtor)) }, 0);
+ if unsafe { libc::pthread_key_create(&mut key, mem::transmute(dtor)) } != 0 {
+ rtabort!("out of TLS keys");
+ }
key
}
diff --git a/library/std/src/sys/thread_local/key/windows.rs b/library/std/src/sys/thread_local/key/windows.rs
index c34c7bc..2ff0fd11 100644
--- a/library/std/src/sys/thread_local/key/windows.rs
+++ b/library/std/src/sys/thread_local/key/windows.rs
@@ -81,15 +81,10 @@ unsafe fn init(&'static self) -> Key {
} else {
let key = unsafe { c::TlsAlloc() };
if key == c::TLS_OUT_OF_INDEXES {
- // Wakeup the waiting threads before panicking to avoid deadlock.
- unsafe {
- c::InitOnceComplete(
- self.once.get(),
- c::INIT_ONCE_INIT_FAILED,
- ptr::null_mut(),
- );
- }
- panic!("out of TLS indexes");
+ // Since we abort the process, there is no need to wake up
+ // the waiting threads. If this were a panic, the wakeup
+ // would need to occur first in order to avoid deadlock.
+ rtabort!("out of TLS indexes");
}
unsafe {
@@ -112,7 +107,9 @@ unsafe fn init(&'static self) -> Key {
// If there is no destructor to clean up, we can use racy initialization.
let key = unsafe { c::TlsAlloc() };
- assert_ne!(key, c::TLS_OUT_OF_INDEXES, "out of TLS indexes");
+ if key == c::TLS_OUT_OF_INDEXES {
+ rtabort!("out of TLS indexes");
+ }
match self.key.compare_exchange(0, key + 1, AcqRel, Acquire) {
Ok(_) => key,