Skip to content

Commit

Permalink
Print thread ID in panic message if thread name is unknown
Browse files Browse the repository at this point in the history
`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>' (id 2) panicked at src/main.rs:3:5:
    explicit panic

There is no change in output for named threads or for threads where an
ID cannot be determined.
  • Loading branch information
tgross35 committed Sep 11, 2023
1 parent 9d311f9 commit 3da1046
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 11 deletions.
14 changes: 11 additions & 3 deletions library/std/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,23 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
let msg = match info.payload().downcast_ref::<&'static str>() {
Some(s) => *s,
None => match info.payload().downcast_ref::<String>() {
Some(s) => &s[..],
Some(s) => s.as_str(),
None => "Box<dyn Any>",
},
};
let thread = thread_info::current_thread();
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");

let write = |err: &mut dyn crate::io::Write, backtrace: Option<BacktraceStyle>| {
let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}");
let _ = match thread.as_ref().map(|t| t.name().ok_or(t)) {
Some(Ok(name)) => {
writeln!(err, "thread '{name}' panicked at {location}:\n{msg}")
}
Some(Err(t)) => {
let id = t.id().as_u64();
writeln!(err, "thread '<unnamed>' (id {id}) panicked at {location}:\n{msg}",)
}
None => writeln!(err, "thread '<unnamed>' panicked at {location}:\n{msg}"),
};

static FIRST_PANIC: AtomicBool = AtomicBool::new(true);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ignore-target-windows: No libc on Windows

//@compile-flags: -Zmiri-disable-abi-check
//@normalize-stderr-test: "thread '<unnamed>' \(id [0-9]+\)" -> "thread '<unnamed>'"

//! Unwinding past the top frame of a stack is Undefined Behavior.
Expand Down
1 change: 1 addition & 0 deletions src/tools/miri/tests/pass/concurrency/simple.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//@compile-flags: -Zmiri-strict-provenance
//@normalize-stderr-test: "thread '<unnamed>' \(id [0-9]+\)" -> "thread '<unnamed>'"

use std::thread;

Expand Down
1 change: 1 addition & 0 deletions src/tools/miri/tests/pass/panic/concurrent-panic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// We are making scheduler assumptions here.
//@compile-flags: -Zmiri-preemption-rate=0
//@normalize-stderr-test: "thread '<unnamed>' \(id [0-9]+\)" -> "thread '<unnamed>'"

//! Cause a panic in one thread while another thread is unwinding. This checks
//! that separate threads have their own panicking state.
Expand Down
14 changes: 8 additions & 6 deletions tests/ui/panics/panic-task-name-none.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
// Test panic error messages for unnamed threads

// run-fail
// error-pattern:thread '<unnamed>' panicked
// regex-error-pattern:thread '<unnamed>' \(id \d+\) panicked
// error-pattern:test
// ignore-emscripten Needs threads

use std::thread;

fn main() {
let r: Result<(), _> = thread::spawn(move || {
panic!("test");
})
.join();
assert!(r.is_ok());
let _: () = thread::spawn(move || {
panic!("test");
})
.join()
.unwrap();
}
2 changes: 1 addition & 1 deletion tests/ui/proc-macro/load-panic-backtrace.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// aux-build:test-macros.rs
// compile-flags: -Z proc-macro-backtrace
// rustc-env:RUST_BACKTRACE=0
// normalize-stderr-test "thread '.*' panicked " -> ""
// normalize-stderr-test "thread '.*' (\(id \d+\) )?panicked " -> ""
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
// needs-unwind proc macro panics to report errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/process/multi-panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn check_for_no_backtrace(test: std::process::Output) {
let err = String::from_utf8_lossy(&test.stderr);
let mut it = err.lines();

assert_eq!(it.next().map(|l| l.starts_with("thread '<unnamed>' panicked")), Some(true));
assert_eq!(it.next().map(|l| l.starts_with("thread '<unnamed>' (id ")), Some(true));
assert_eq!(it.next().is_some(), true);
assert_eq!(it.next(), Some("note: run with `RUST_BACKTRACE=1` \
environment variable to display a backtrace"));
Expand Down

0 comments on commit 3da1046

Please sign in to comment.