about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-06-03 21:53:36 +0200
committerGitHub <noreply@github.com>2025-06-03 21:53:36 +0200
commitd096ebf8d93e78b429c5c5866ecc60b3a5d9ed18 (patch)
treeaebd489ff5f107259759c39157951aeb37b72d77
parent27a894f86f361adee3ff5b25d685bb117c623461 (diff)
parent8bf515330fb68ba10a54e9087a2b5629a968e766 (diff)
downloadrust-d096ebf8d93e78b429c5c5866ecc60b3a5d9ed18.tar.gz
rust-d096ebf8d93e78b429c5c5866ecc60b3a5d9ed18.zip
Rollup merge of #141455 - joboet:tls_exhaustion_abort, r=tgross35
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.
-rw-r--r--library/std/src/sys/thread_local/key/unix.rs4
-rw-r--r--library/std/src/sys/thread_local/key/windows.rs17
2 files changed, 10 insertions, 11 deletions
diff --git a/library/std/src/sys/thread_local/key/unix.rs b/library/std/src/sys/thread_local/key/unix.rs
index 93bd0d1f668..8fa24265e43 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 type Key = libc::pthread_key_t;
 #[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 c34c7bc204f..2ff0fd1196e 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 @@ impl LazyKey {
             } 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 @@ impl LazyKey {
             // 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,