Skip to content

Print thread ID in panic message #115746

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

tgross35
Copy link
Contributor

@tgross35 tgross35 commented Sep 11, 2023

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: dist-x86_64-freebsd
try-job: dist-x86_64-linux
try-job: dist-x86_64-linux-alt
try-job: dist-x86_64-netbsd

@rustbot
Copy link
Collaborator

rustbot commented Sep 11, 2023

r? @davidtwco

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Sep 11, 2023
@tgross35
Copy link
Contributor Author

tgross35 commented Sep 11, 2023

I think this needs FCP since it's a visible change

@rustbot label -T-libs -T-compiler +T-libs-api
r? libs-api

@rustbot rustbot added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Sep 11, 2023
@rustbot rustbot assigned joshtriplett and unassigned davidtwco Sep 11, 2023
@tgross35 tgross35 force-pushed the unnamed-threads-panic-message branch from d68fab6 to 371dd28 Compare September 11, 2023 05:35
@rustbot
Copy link
Collaborator

rustbot commented Sep 11, 2023

The Miri subtree was changed

cc @rust-lang/miri

@tgross35 tgross35 force-pushed the unnamed-threads-panic-message branch 2 times, most recently from 8e72037 to 3da1046 Compare September 11, 2023 06:13
@rustbot rustbot removed the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Sep 11, 2023
@tgross35
Copy link
Contributor Author

cc @m-ou-se since you recently did the formatting in #112849

@bjorn3
Copy link
Member

bjorn3 commented Sep 11, 2023

Maybe

thread '<unnamed 2>' panicked at src/main.rs:3:5:
explicit panic

or

thread '<unnamed#2>' panicked at src/main.rs:3:5:
explicit panic

? That fits more with the way named threads are shown.

@the8472
Copy link
Member

the8472 commented Sep 11, 2023

Note that this is a rust-internal thread ID, which isn't the OS thread ID which can be relevant if you're also logging from C code or looking at things with GDB. And as_u64() is unstable and there are questions about stabilizing it (#110738).

@tgross35
Copy link
Contributor Author

tgross35 commented Sep 11, 2023

Maybe

thread '<unnamed 2>' panicked at src/main.rs:3:5:
explicit panic

or

thread '<unnamed#2>' panicked at src/main.rs:3:5:
explicit panic

I just proposed the syntax as a demo, figured libs-api would make the final choice - though between those two, I like the first one better

Note that this is a rust-internal thread ID, which isn't the OS thread ID which can be relevant if you're also logging from C code or looking at things with GDB. And as_u64() is unstable and there are questions about stabilizing it (#110738).

It is kind of unfortunate that Rust and C won't use the same thread IDs. But this seems worthwhile still - Rust-only applications printing the thread ID in logs is common (tracing even has a builtin way to do this), probably more common than Rust thread IDs silently mixing with C thread IDs in logs. And even in that case, it still gives you something more concrete to trace than "something failed".

This is all inspired by the below failure I recently had in an highly threaded system. The entire backtrace uselessly displayed one repeated function, with no hints about which preceding log events were relevant:

thread '<unnamed>' panicked at src/scan.rs:101:55:
called `Result::unwrap()` on an `Err` value: ()
stack backtrace:
   0:        0x1009661d0 - __mh_execute_header
   1:        0x10088869b - __mh_execute_header
   2:        0x10093ba0e - __mh_execute_header
   4:        0x10096757c - __mh_execute_header
   5:        0x100968632 - __mh_execute_header
   6:        0x1009680f4 - __mh_execute_header
   7:        0x100968059 - __mh_execute_header
   8:        0x100968042 - __mh_execute_header
   9:        0x100bdd913 - __mh_execute_header

I don't think that stability of the thread ID is much of a concern since we will always have some integer ID for a thread, even if the semantics of that ID might change. The important thing is probably just that this panic message thread ID is the same as what shows up as Debug for ThreadId (or as_u64 as applicable) since that is what other libraries are directed to use. That is the case here

@tgross35
Copy link
Contributor Author

tgross35 commented Sep 15, 2023

Another display option - it looks a bit cleaner to not even call out that a thread is unnamed, and I don't think it adds much

thread with ID 2 panicked at src/main.rs:3:5:
explicit panic

Or we could use ThreadId's debug formatting which tracing and I think log do, but that seems unnecessarily clunky

thread with `ThreadId(2)` panicked at src/main.rs:3:5:
explicit panic

I also tried to poke some discussion at #67939

@bors
Copy link
Collaborator

bors commented Sep 19, 2023

☔ The latest upstream changes (presumably #115627) made this pull request unmergeable. Please resolve the merge conflicts.

@tgross35
Copy link
Contributor Author

@joshtriplett do you have any thoughts on this?

@tgross35 tgross35 force-pushed the unnamed-threads-panic-message branch from 3da1046 to e055544 Compare November 9, 2023 17:20
@timClicks
Copy link
Contributor

Sorry to add bike shedding to the thread. Here is a slight derivative of the last suggestion, which omits a "with":

thread `ThreadId(2)` panicked at src/main.rs:3:5:
explicit panic

Although it's uglier than using the thread identifier in a sentence, using the Debug form makes it look like a Rust value rather than something else. It's also consistent with other output from Rust, although the case can definitely be made that thread IDs deserve a special case.

@tgross35
Copy link
Contributor Author

tgross35 commented Dec 1, 2023

I know Josh has a pretty busy queue, so perhaps it is best to reroll

r? libs-api

@rustbot rustbot assigned dtolnay and unassigned joshtriplett Dec 1, 2023
@dtolnay
Copy link
Member

dtolnay commented Dec 1, 2023

I think this needs FCP since it's a visible change

@​rustbot label -T-libs -T-compiler +T-libs-api

I think it wouldn't need one. T-libs-api FCP is primarily for any time a permanent API commitment is being made by the standard library, and deprecations. In contrast, anything that we can just change back with minimal effort or disruption would not warrant FCP.

#112849 had a T-libs FCP but I am not familiar with their criteria for that. @rust-lang/libs would you want to handle this PR?

In any case, this looks good to me.

@thomcc
Copy link
Member

thomcc commented Dec 1, 2023

I don't know that this needs FCP. I'm not opposed and there is precedent for it, but OTOH we wouldn't FCP a panic message change somewhere in the stdlib. So I don't feel strongly.

In any case, I think this change is a good idea, and am in favor.

tgross35 added a commit to tgross35/miri that referenced this pull request Jun 18, 2025
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri.

These should be useful in general but should also help support printing
the OS thread ID in panic messages [1].

[1]: rust-lang/rust#115746
tgross35 added a commit to tgross35/rust that referenced this pull request Jun 18, 2025
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri.

These should be useful in general but should also help support printing
the OS thread ID in panic messages [1].

[1]: rust-lang#115746
@tgross35 tgross35 force-pushed the unnamed-threads-panic-message branch from 2bfd098 to b9c2dc2 Compare June 18, 2025 22:06
tgross35 added a commit to tgross35/miri that referenced this pull request Jun 19, 2025
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri. The
syscall and extern symbol is included as well on Linux.

These should be useful in general but should also help support printing
the OS thread ID in panic messages [1].

[1]: rust-lang/rust#115746
tgross35 added 3 commits June 19, 2025 05:16
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri. The
syscall and extern symbol is included as well on Linux.

These should be useful in general but should also help support printing
the OS thread ID in panic messages [1].

[1]: rust-lang#115746
So we don't need to add normalization to every test that includes a
panic message, add a global normalization to compiletest.
`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>' (0xff9bf) 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.

Work around stage1 vs. stage2 differences in miri
@tgross35 tgross35 force-pushed the unnamed-threads-panic-message branch from b9c2dc2 to 0cd5add Compare June 19, 2025 05:17
tgross35 added a commit to tgross35/miri that referenced this pull request Jun 24, 2025
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri. The
syscall and extern symbol is included as well on Linux.

These should be useful in general but should also help support printing
the OS thread ID in panic messages [1].

[1]: rust-lang/rust#115746
@tgross35
Copy link
Contributor Author

For the remaining targets: @jclulow, @psumbera, @jethrogb, @jackpot51, do Illumos, Solaris, Fortanix, or Redox provide a way to get a current thread ID? I haven't been able to find anything documented.

@joshtriplett
Copy link
Member

@rfcbot resolved ambiguous-non-os-thread-id

@rfcbot rfcbot added the final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. label Jun 25, 2025
@rfcbot
Copy link
Collaborator

rfcbot commented Jun 25, 2025

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot rfcbot removed the proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. label Jun 25, 2025
@jclulow
Copy link
Contributor

jclulow commented Jun 26, 2025

For the remaining targets: @jclulow, @psumbera, @jethrogb, @jackpot51, do Illumos, Solaris, Fortanix, or Redox provide a way to get a current thread ID? I haven't been able to find anything documented.

Do you mean the name of the thread provided to the thread builder? If so, I believe you can read that from the lwpname file described in proc(5).

@cuviper
Copy link
Member

cuviper commented Jun 26, 2025

Not the name -- we're looking for a numeric thread ID, like Linux's gettid().

@jclulow
Copy link
Contributor

jclulow commented Jun 26, 2025

Oh, sorry. You probably want either the native thr_self(3C) then, or the pthread alias equivalent pthread_self(3C) which I believe is standard and I assume must be available anywhere you have pthreads support.

@tgross35
Copy link
Contributor Author

I believe pthread_self is allowed to return an ID assigned by the threading library, whereas the functions we use here are an OS thread ID (at least to the best of my knowledge; gettid, getthrid, pthread_getthreadid_np, _lwp_self, pthread_threadid_np all return an integer or some pid_t rather than {p}thread_t). The downside of the pthread ID is that might not line up with the OS thread IDs from /proc or sysctl for debuggers or process viewers to use. But maybe those coincide on Illumos - any idea if that might be the case?

Admittedly I think it's probably to use pthread_self in any case if there isn't anything like described.

@jclulow
Copy link
Contributor

jclulow commented Jun 26, 2025

I believe they all coincide on illumos, yes. Our threading model is 1:1, where a user visible (i.e., libc level) thread is directly equivalent to an LWP (light weight process) which is what the kernel uses to save and restore user register state. So the LWP/thread with ID 1 is the main thread, no matter where you look, and subsequent threads have higher ID numbers, etc. The same IDs are also used in /proc paths (for debuggers and process control tools) and DTrace and so on. Note that these IDs are scoped within a process (every process starts with an LWP 1), not globally unique like task IDs on Linux.

@tgross35
Copy link
Contributor Author

That's easy then, thanks for confirming!

@psumbera
Copy link
Contributor

That's easy then, thanks for confirming!

Solaris should be treated the same way as Illumos please.

@jethrogb
Copy link
Contributor

For SGX: https://github.com/rust-lang/rust/blob/master/library/std/src/sys/pal/sgx/abi/thread.rs#L8

@bors
Copy link
Collaborator

bors commented Jun 27, 2025

☔ The latest upstream changes (presumably #143091) made this pull request unmergeable. Please resolve the merge conflicts.

@jackpot51
Copy link
Contributor

@tgross35 Redox OS has gettid

tgross35 added a commit to tgross35/miri that referenced this pull request Jun 28, 2025
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri. The
syscall and extern symbol is included as well on Linux.

These should be useful in general but should also help support printing
the OS thread ID in panic messages [1].

[1]: rust-lang/rust#115746
tgross35 added a commit to tgross35/miri that referenced this pull request Jun 28, 2025
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri. The
syscall and extern symbol is included as well on Linux.

These should be useful in general but should also help support printing
the OS thread ID in panic messages [1].

[1]: rust-lang/rust#115746
tgross35 added a commit to tgross35/miri that referenced this pull request Jun 29, 2025
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri. The
syscall and extern symbol is included as well on Linux.

These should be useful in general but will also help support printing
the OS thread ID in panic messages [1].

[1]: rust-lang/rust#115746

Squashed commit from Ralf:

    try_from_scalar: extend comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-compiletest Area: The compiletest test runner A-run-make Area: port run-make Makefiles to rmake.rs A-testsuite Area: The testsuite used to check the correctness of rustc disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. O-hermit Operating System: Hermit O-itron Operating System: ITRON O-SGX Target: SGX O-unix Operating system: Unix-like O-wasi Operating system: Wasi, Webassembly System Interface O-windows Operating system: Windows rla-silenced Silences rust-log-analyzer postings to the PR it's added on. S-waiting-on-fcp Status: PR is in FCP and is awaiting for FCP to complete. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.