From 5009847d1461d2af722dc154a00614765a80ac16 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 17 Sep 2025 17:24:25 +0200 Subject: [PATCH 1/2] std: don't call `current_os_id` from signal handler --- .../std/src/sys/pal/unix/stack_overflow.rs | 33 ++++++++++--------- .../pal/unix/stack_overflow/thread_info.rs | 10 ++++-- library/std/src/sys/thread/unix.rs | 9 +++-- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 226b6bce01b58..040fda75a5080 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -8,8 +8,8 @@ pub struct Handler { } impl Handler { - pub unsafe fn new(thread_name: Option>) -> Handler { - make_handler(false, thread_name) + pub unsafe fn new() -> Handler { + make_handler(false) } fn null() -> Handler { @@ -117,8 +117,15 @@ mod imp { if let Some(thread_info) = thread_info && thread_info.guard_page_range.contains(&fault_addr) { - let name = thread_info.thread_name.as_deref().unwrap_or(""); - let tid = crate::thread::current_os_id(); + // Hey you! Yes, you modifying the stack overflow message! + // Please make sure that all functions called here are + // actually async-signal-safe. If they're not, try retrieving + // the information beforehand and storing it in `ThreadInfo`. + // Thank you! + // - says Jonas after having had to watch his carefully + // written code get made unsound again. + let tid = thread_info.tid; + let name = thread_info.name.as_deref().unwrap_or(""); rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); rtabort!("stack overflow"); } @@ -164,12 +171,12 @@ mod imp { if !NEED_ALTSTACK.load(Ordering::Relaxed) { // haven't set up our sigaltstack yet NEED_ALTSTACK.store(true, Ordering::Release); - let handler = unsafe { make_handler(true, None) }; + let handler = unsafe { make_handler(true) }; MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); mem::forget(handler); if let Some(guard_page_range) = guard_page_range.take() { - set_current_info(guard_page_range, Some(Box::from("main"))); + set_current_info(guard_page_range); } } @@ -240,14 +247,14 @@ mod imp { /// # Safety /// Mutates the alternate signal stack #[forbid(unsafe_op_in_unsafe_fn)] - pub unsafe fn make_handler(main_thread: bool, thread_name: Option>) -> Handler { + pub unsafe fn make_handler(main_thread: bool) -> Handler { if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { return Handler::null(); } if !main_thread { if let Some(guard_page_range) = unsafe { current_guard() } { - set_current_info(guard_page_range, thread_name); + set_current_info(guard_page_range); } } @@ -633,10 +640,7 @@ mod imp { pub unsafe fn cleanup() {} - pub unsafe fn make_handler( - _main_thread: bool, - _thread_name: Option>, - ) -> super::Handler { + pub unsafe fn make_handler(_main_thread: bool) -> super::Handler { super::Handler::null() } @@ -720,10 +724,7 @@ mod imp { pub unsafe fn cleanup() {} - pub unsafe fn make_handler( - main_thread: bool, - _thread_name: Option>, - ) -> super::Handler { + pub unsafe fn make_handler(main_thread: bool) -> super::Handler { if !main_thread { reserve_stack(); } diff --git a/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs b/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs index e81429b98a6c7..42eb0cd9a61af 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs @@ -32,8 +32,9 @@ use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sys::os::errno_location; pub struct ThreadInfo { + pub tid: u64, + pub name: Option>, pub guard_page_range: Range, - pub thread_name: Option>, } static LOCK: Mutex<()> = Mutex::new(()); @@ -108,14 +109,17 @@ fn spin_lock_in_setup(this: usize) -> UnlockOnDrop { } } -pub fn set_current_info(guard_page_range: Range, thread_name: Option>) { +pub fn set_current_info(guard_page_range: Range) { + let tid = crate::thread::current_os_id(); + let name = crate::thread::with_current_name(|name| name.map(Box::from)); + let this = errno_location().addr(); let _lock_guard = LOCK.lock(); let _spin_guard = spin_lock_in_setup(this); // SAFETY: we own the spin lock, so `THREAD_INFO` cannot be aliased. let thread_info = unsafe { &mut *(&raw mut THREAD_INFO) }; - thread_info.insert(this, ThreadInfo { guard_page_range, thread_name }); + thread_info.insert(this, ThreadInfo { tid, name, guard_page_range }); } pub fn delete_current_info() { diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index d4c27097afd79..4adc94d0e5c9e 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -14,7 +14,7 @@ use crate::sys::weak::dlsym; #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto",))] use crate::sys::weak::weak; use crate::sys::{os, stack_overflow}; -use crate::thread::{ThreadInit, current}; +use crate::thread::ThreadInit; use crate::time::Duration; use crate::{cmp, io, ptr}; #[cfg(not(any( @@ -111,10 +111,9 @@ impl Thread { let init = Box::from_raw(data as *mut ThreadInit); let rust_start = init.init(); - // Set up our thread name and stack overflow handler which may get triggered - // if we run out of stack. - let thread = current(); - let _handler = stack_overflow::Handler::new(thread.name().map(Box::from)); + // Now that the thread information is set, set up our stack + // overflow handler. + let _handler = stack_overflow::Handler::new(); rust_start(); } From d4af0f07729e1ce75e35f6c15ae5bab0830db760 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Sun, 30 Nov 2025 20:29:26 +0900 Subject: [PATCH 2/2] Fix indent in E0591.md --- .../rustc_error_codes/src/error_codes/E0591.md | 16 ++++++++-------- tests/ui/explain/basic.stdout | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0591.md b/compiler/rustc_error_codes/src/error_codes/E0591.md index 6ed8370e8c1c7..c32aa95a3bfdd 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0591.md +++ b/compiler/rustc_error_codes/src/error_codes/E0591.md @@ -62,14 +62,14 @@ This pattern should be rewritten. There are a few possible ways to do this: and do the cast in the fn body (the preferred option) - cast the fn item of a fn pointer before calling transmute, as shown here: - ``` - # extern "C" fn foo(_: Box) {} - # use std::mem::transmute; - # unsafe { - let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); - let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too - # } - ``` +``` +# extern "C" fn foo(_: Box) {} +# use std::mem::transmute; +# unsafe { +let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); +let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too +# } +``` The same applies to transmutes to `*mut fn()`, which were observed in practice. Note though that use of this type is generally incorrect. diff --git a/tests/ui/explain/basic.stdout b/tests/ui/explain/basic.stdout index ef1d866c3ff3b..6377768d4785d 100644 --- a/tests/ui/explain/basic.stdout +++ b/tests/ui/explain/basic.stdout @@ -56,10 +56,10 @@ This pattern should be rewritten. There are a few possible ways to do this: and do the cast in the fn body (the preferred option) - cast the fn item of a fn pointer before calling transmute, as shown here: - ``` - let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); - let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too - ``` +``` +let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); +let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too +``` The same applies to transmutes to `*mut fn()`, which were observed in practice. Note though that use of this type is generally incorrect.