From 820ffc8d7ad9741a078634a42f14ea373d565467 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 19 May 2022 17:21:20 -0400 Subject: [PATCH 1/2] Call the OS function to set the main thread's name on program init Normally, `Thread::spawn` takes care of setting the thread's name, if one was provided, but since the main thread wasn't created by calling `Thread::spawn`, we need to call that function in `std::rt::init`. This is mainly useful for system tools like debuggers and profilers which might show the thread name to a user. Prior to these changes, gdb and WinDbg would show all thread names except the main thread's name to a user. I've validated that this patch resolves the issue for both debuggers. --- library/std/src/sys/unix/mod.rs | 10 ++++++++ library/std/src/sys/windows/mod.rs | 6 ++++- src/test/debuginfo/thread-names.rs | 40 ++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/test/debuginfo/thread-names.rs diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 8e909aab7f0..1505878e18c 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -1,5 +1,6 @@ #![allow(missing_docs, nonstandard_style)] +use crate::ffi::CStr; use crate::io::ErrorKind; pub use self::rand::hashmap_random_keys; @@ -66,6 +67,15 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { stack_overflow::init(); args::init(argc, argv); + // Normally, `thread::spawn` will call `Thread::set_name` but since this thread + // already exists, we have to call it ourselves. We only do this on macos + // because some unix-like operating systems such as Linux share process-id and + // thread-id for the main thread and so renaming the main thread will rename the + // process and we only want to enable this on platforms we've tested. + if cfg!(target_os = "macos") { + thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0")); + } + unsafe fn sanitize_standard_fds() { #[cfg(not(miri))] // The standard fds are always available in Miri. diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index 4e9d408291d..b3f6d2d0aae 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -1,6 +1,6 @@ #![allow(missing_docs, nonstandard_style)] -use crate::ffi::{OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString}; use crate::io::ErrorKind; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::path::PathBuf; @@ -49,6 +49,10 @@ cfg_if::cfg_if! { // NOTE: this is not guaranteed to run, for example when Rust code is called externally. pub unsafe fn init(_argc: isize, _argv: *const *const u8) { stack_overflow::init(); + + // Normally, `thread::spawn` will call `Thread::set_name` but since this thread already + // exists, we have to call it ourselves. + thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0")); } // SAFETY: must be called only once during runtime cleanup. diff --git a/src/test/debuginfo/thread-names.rs b/src/test/debuginfo/thread-names.rs new file mode 100644 index 00000000000..f42a7aec3bd --- /dev/null +++ b/src/test/debuginfo/thread-names.rs @@ -0,0 +1,40 @@ +// compile-flags:-g +// We can't set the main thread name on Linux because it renames the process (#97191) +// ignore-linux + +// === GDB TESTS ================================================================================== +// +// gdb-command:run +// +// gdb-command:info threads +// gdb-check: 1 Thread [...] [...] "main" [...] +// gdb-check:* 2 Thread [...] [...] "my new thread" [...] + +// === LLDB TESTS ================================================================================= +// +// lldb-command:run +// +// lldb-command:thread info 1 +// lldb-check:thread #1:[...]name = 'main'[...] +// lldb-command:thread info 2 +// lldb-check:thread #2:[...]name = 'my new thread'[...] + +// === CDB TESTS ================================================================================== +// +// cdb-command:g +// +// cdb-command:~ +// cdb-check: 0 Id: [...] Suspend: 1 Teb: [...] Unfrozen "main" +// cdb-check:. [...] Id: [...] Suspend: 1 Teb: [...] Unfrozen "my new thread" + +use std::thread; + +fn main() { + let handle = thread::Builder::new().name("my new thread".into()).spawn(|| { + zzz(); // #break + }).unwrap(); + + handle.join().unwrap(); +} + +fn zzz() {} From cb87ce22857bef0cf57a919d4c415211f0b1ab1d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 3 Jun 2022 11:36:54 -0400 Subject: [PATCH 2/2] Update src/test/debuginfo/thread-names.rs Co-authored-by: Chris Denton --- src/test/debuginfo/thread-names.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/debuginfo/thread-names.rs b/src/test/debuginfo/thread-names.rs index f42a7aec3bd..7a35a518946 100644 --- a/src/test/debuginfo/thread-names.rs +++ b/src/test/debuginfo/thread-names.rs @@ -1,6 +1,17 @@ // compile-flags:-g // We can't set the main thread name on Linux because it renames the process (#97191) // ignore-linux +// ignore-android +// ignore-dragonfly +// ignore-emscripten +// ignore-freebsd +// ignore-haiku +// ignore-ios +// ignore-netbsd +// ignore-openbsd +// ignore-solaris +// ignore-sgx +// ignore-windows-gnu // === GDB TESTS ================================================================================== //