Auto merge of #97191 - wesleywiser:main_thread_name, r=ChrisDenton

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.
This commit is contained in:
bors 2022-06-04 20:27:53 +00:00
commit 4e725bad73
3 changed files with 66 additions and 1 deletions

View File

@ -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.

View File

@ -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 @@
// 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.

View File

@ -0,0 +1,51 @@
// 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 ==================================================================================
//
// 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() {}