Skip to content

Commit 61cb1e9

Browse files
committed
Auto merge of #115746 - tgross35:unnamed-threads-panic-message, r=cuviper
Print thread ID in panic message `panic!` does not print any identifying information for threads that are unnamed. However, in many cases, the thread ID can be determined. This changes the panic message from something like this: thread '<unnamed>' panicked at src/main.rs:3:5: explicit panic To something like this: thread '<unnamed>' (12345) panicked at src/main.rs:3:5: explicit panic Stack overflow messages are updated as well. This change applies to both named and unnamed threads. The ID printed is the OS integer thread ID rather than the Rust thread ID, which should also be what debuggers print. try-job: aarch64-apple try-job: aarch64-gnu try-job: dist-apple-various try-job: dist-various-* try-job: dist-x86_64-freebsd try-job: dist-x86_64-illumos try-job: dist-x86_64-netbsd try-job: dist-x86_64-solaris try-job: test-various try-job: x86_64-gnu try-job: x86_64-mingw-1 try-job: x86_64-msvc-1
2 parents 6bcdcc7 + 289fe36 commit 61cb1e9

File tree

124 files changed

+318
-169
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+318
-169
lines changed

library/std/src/panicking.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ fn default_hook(info: &PanicHookInfo<'_>) {
269269

270270
thread::with_current_name(|name| {
271271
let name = name.unwrap_or("<unnamed>");
272+
let tid = thread::current_os_id();
272273

273274
// Try to write the panic message to a buffer first to prevent other concurrent outputs
274275
// interleaving with it.
@@ -277,7 +278,7 @@ fn default_hook(info: &PanicHookInfo<'_>) {
277278

278279
let write_msg = |dst: &mut dyn crate::io::Write| {
279280
// We add a newline to ensure the panic message appears at the start of a line.
280-
writeln!(dst, "\nthread '{name}' panicked at {___location}:\n{msg}")
281+
writeln!(dst, "\nthread '{name}' ({tid}) panicked at {___location}:\n{msg}")
281282
};
282283

283284
if write_msg(&mut cursor).is_ok() {

library/std/src/sys/pal/hermit/thread.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ impl Thread {
115115
}
116116
}
117117

118+
pub(crate) fn current_os_id() -> Option<u64> {
119+
None
120+
}
121+
118122
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
119123
unsafe { Ok(NonZero::new_unchecked(hermit_abi::available_parallelism())) }
120124
}

library/std/src/sys/pal/itron/thread.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,10 @@ unsafe fn terminate_and_delete_current_task() -> ! {
361361
unsafe { crate::hint::unreachable_unchecked() };
362362
}
363363

364+
pub(crate) fn current_os_id() -> Option<u64> {
365+
None
366+
}
367+
364368
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
365369
super::unsupported()
366370
}

library/std/src/sys/pal/sgx/thread.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![cfg_attr(test, allow(dead_code))] // why is this necessary?
22

3-
use super::abi::usercalls;
3+
use super::abi::{thread, usercalls};
44
use super::unsupported;
55
use crate::ffi::CStr;
66
use crate::io;
@@ -149,6 +149,10 @@ impl Thread {
149149
}
150150
}
151151

152+
pub(crate) fn current_os_id() -> Option<u64> {
153+
Some(thread::current().addr().get() as u64)
154+
}
155+
152156
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
153157
unsupported()
154158
}

library/std/src/sys/pal/teeos/thread.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ impl Drop for Thread {
144144
}
145145
}
146146

147+
pub(crate) fn current_os_id() -> Option<u64> {
148+
None
149+
}
150+
147151
// Note: Both `sched_getaffinity` and `sysconf` are available but not functional on
148152
// teeos, so this function always returns an Error!
149153
pub fn available_parallelism() -> io::Result<NonZero<usize>> {

library/std/src/sys/pal/uefi/thread.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ impl Thread {
5656
}
5757
}
5858

59+
pub(crate) fn current_os_id() -> Option<u64> {
60+
None
61+
}
62+
5963
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
6064
// UEFI is single threaded
6165
Ok(NonZero::new(1).unwrap())

library/std/src/sys/pal/unix/stack_overflow.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ mod imp {
119119
&& thread_info.guard_page_range.contains(&fault_addr)
120120
{
121121
let name = thread_info.thread_name.as_deref().unwrap_or("<unknown>");
122-
rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
122+
let tid = crate::thread::current_os_id();
123+
rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n");
123124
rtabort!("stack overflow");
124125
}
125126
})
@@ -696,7 +697,8 @@ mod imp {
696697
if code == c::EXCEPTION_STACK_OVERFLOW {
697698
crate::thread::with_current_name(|name| {
698699
let name = name.unwrap_or("<unknown>");
699-
rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
700+
let tid = crate::thread::current_os_id();
701+
rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n");
700702
});
701703
}
702704
c::EXCEPTION_CONTINUE_SEARCH

library/std/src/sys/pal/unix/thread.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,62 @@ impl Drop for Thread {
398398
}
399399
}
400400

401+
pub(crate) fn current_os_id() -> Option<u64> {
402+
// Most Unix platforms have a way to query an integer ID of the current thread, all with
403+
// slightly different spellings.
404+
//
405+
// The OS thread ID is used rather than `pthread_self` so as to match what will be displayed
406+
// for process inspection (debuggers, trace, `top`, etc.).
407+
cfg_if::cfg_if! {
408+
// Most platforms have a function returning a `pid_t` or int, which is an `i32`.
409+
if #[cfg(any(target_os = "android", target_os = "linux"))] {
410+
use crate::sys::weak::syscall;
411+
412+
// `libc::gettid` is only available on glibc 2.30+, but the syscall is available
413+
// since Linux 2.4.11.
414+
syscall!(fn gettid() -> libc::pid_t;);
415+
416+
// SAFETY: FFI call with no preconditions.
417+
let id: libc::pid_t = unsafe { gettid() };
418+
Some(id as u64)
419+
} else if #[cfg(target_os = "nto")] {
420+
// SAFETY: FFI call with no preconditions.
421+
let id: libc::pid_t = unsafe { libc::gettid() };
422+
Some(id as u64)
423+
} else if #[cfg(target_os = "openbsd")] {
424+
// SAFETY: FFI call with no preconditions.
425+
let id: libc::pid_t = unsafe { libc::getthrid() };
426+
Some(id as u64)
427+
} else if #[cfg(target_os = "freebsd")] {
428+
// SAFETY: FFI call with no preconditions.
429+
let id: libc::c_int = unsafe { libc::pthread_getthreadid_np() };
430+
Some(id as u64)
431+
} else if #[cfg(target_os = "netbsd")] {
432+
// SAFETY: FFI call with no preconditions.
433+
let id: libc::lwpid_t = unsafe { libc::_lwp_self() };
434+
Some(id as u64)
435+
} else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] {
436+
// On Illumos and Solaris, the `pthread_t` is the same as the OS thread ID.
437+
// SAFETY: FFI call with no preconditions.
438+
let id: libc::pthread_t = unsafe { libc::pthread_self() };
439+
Some(id as u64)
440+
} else if #[cfg(target_vendor = "apple")] {
441+
// Apple allows querying arbitrary thread IDs, `thread=NULL` queries the current thread.
442+
let mut id = 0u64;
443+
// SAFETY: `thread_id` is a valid pointer, no other preconditions.
444+
let status: libc::c_int = unsafe { libc::pthread_threadid_np(0, &mut id) };
445+
if status == 0 {
446+
Some(id)
447+
} else {
448+
None
449+
}
450+
} else {
451+
// Other platforms don't have an OS thread ID or don't have a way to access it.
452+
None
453+
}
454+
}
455+
}
456+
401457
#[cfg(any(
402458
target_os = "linux",
403459
target_os = "nto",

library/std/src/sys/pal/unsupported/thread.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ impl Thread {
3939
}
4040
}
4141

42+
pub(crate) fn current_os_id() -> Option<u64> {
43+
None
44+
}
45+
4246
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
4347
unsupported()
4448
}

library/std/src/sys/pal/wasi/thread.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ impl Thread {
194194
}
195195
}
196196

197+
pub(crate) fn current_os_id() -> Option<u64> {
198+
None
199+
}
200+
197201
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
198202
cfg_if::cfg_if! {
199203
if #[cfg(target_feature = "atomics")] {

0 commit comments

Comments
 (0)