Skip to content

Commit 1af11b1

Browse files
authored
Rollup merge of rust-lang#121666 - ChrisDenton:thread-name, r=cuviper
Use the OS thread name by default if `THREAD_INFO` has not been initialized Currently if `THREAD_INFO` hasn't been initialized then the name will be set to `None`. This PR changes it to use the OS thread name by default. This mostly affects foreign threads at the moment but we could expand this to make more use of the OS thread name in the future. Note: I've only implemented `Thread::get_name` for windows, linux and macos (and macos adjacent) targets. The rest just return `None`.
2 parents 49775dd + 6cb0c40 commit 1af11b1

File tree

15 files changed

+137
-11
lines changed

15 files changed

+137
-11
lines changed

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use super::abi;
44
use super::thread_local_dtor::run_dtors;
5-
use crate::ffi::CStr;
5+
use crate::ffi::{CStr, CString};
66
use crate::io;
77
use crate::mem;
88
use crate::num::NonZero;
@@ -71,6 +71,10 @@ impl Thread {
7171
// nope
7272
}
7373

74+
pub fn get_name() -> Option<CString> {
75+
None
76+
}
77+
7478
#[inline]
7579
pub fn sleep(dur: Duration) {
7680
unsafe {

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use super::{
88
};
99
use crate::{
1010
cell::UnsafeCell,
11-
ffi::CStr,
11+
ffi::{CStr, CString},
1212
hint, io,
1313
mem::ManuallyDrop,
1414
num::NonZero,
@@ -204,6 +204,10 @@ impl Thread {
204204
// nope
205205
}
206206

207+
pub fn get_name() -> Option<CString> {
208+
None
209+
}
210+
207211
pub fn sleep(dur: Duration) {
208212
for timeout in dur2reltims(dur) {
209213
expect_success(unsafe { abi::dly_tsk(timeout) }, &"dly_tsk");

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![cfg_attr(test, allow(dead_code))] // why is this necessary?
22
use super::unsupported;
3-
use crate::ffi::CStr;
3+
use crate::ffi::{CStr, CString};
44
use crate::io;
55
use crate::num::NonZero;
66
use crate::time::Duration;
@@ -133,6 +133,10 @@ impl Thread {
133133
// which succeeds as-is with the SGX target.
134134
}
135135

136+
pub fn get_name() -> Option<CString> {
137+
None
138+
}
139+
136140
pub fn sleep(dur: Duration) {
137141
usercalls::wait_timeout(0, dur, || true);
138142
}

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::convert::TryInto;
22

33
use crate::cmp;
4-
use crate::ffi::CStr;
4+
use crate::ffi::{CStr, CString};
55
use crate::io;
66
use crate::mem;
77
use crate::num::NonZero;
@@ -101,6 +101,10 @@ impl Thread {
101101
// contact the teeos rustzone team.
102102
}
103103

104+
pub fn get_name() -> Option<CString> {
105+
None
106+
}
107+
104108
/// only main thread could wait for sometime in teeos
105109
pub fn sleep(dur: Duration) {
106110
let sleep_millis = dur.as_millis();

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::unsupported;
2-
use crate::ffi::CStr;
2+
use crate::ffi::{CStr, CString};
33
use crate::io;
44
use crate::num::NonZero;
55
use crate::ptr::NonNull;
@@ -23,6 +23,10 @@ impl Thread {
2323
// nope
2424
}
2525

26+
pub fn get_name() -> Option<CString> {
27+
None
28+
}
29+
2630
pub fn sleep(dur: Duration) {
2731
let boot_services: NonNull<r_efi::efi::BootServices> =
2832
crate::os::uefi::env::boot_services().expect("can't sleep").cast();

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

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::cmp;
2-
use crate::ffi::CStr;
2+
use crate::ffi::{CStr, CString};
33
use crate::io;
44
use crate::mem;
55
use crate::num::NonZero;
@@ -225,6 +225,44 @@ impl Thread {
225225
// Newlib, Emscripten, and VxWorks have no way to set a thread name.
226226
}
227227

228+
#[cfg(target_os = "linux")]
229+
pub fn get_name() -> Option<CString> {
230+
const TASK_COMM_LEN: usize = 16;
231+
let mut name = vec![0u8; TASK_COMM_LEN];
232+
let res = unsafe {
233+
libc::pthread_getname_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len())
234+
};
235+
if res != 0 {
236+
return None;
237+
}
238+
name.truncate(name.iter().position(|&c| c == 0)?);
239+
CString::new(name).ok()
240+
}
241+
242+
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
243+
pub fn get_name() -> Option<CString> {
244+
let mut name = vec![0u8; libc::MAXTHREADNAMESIZE];
245+
let res = unsafe {
246+
libc::pthread_getname_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len())
247+
};
248+
if res != 0 {
249+
return None;
250+
}
251+
name.truncate(name.iter().position(|&c| c == 0)?);
252+
CString::new(name).ok()
253+
}
254+
255+
#[cfg(not(any(
256+
target_os = "linux",
257+
target_os = "macos",
258+
target_os = "ios",
259+
target_os = "tvos",
260+
target_os = "watchos"
261+
)))]
262+
pub fn get_name() -> Option<CString> {
263+
None
264+
}
265+
228266
#[cfg(not(target_os = "espidf"))]
229267
pub fn sleep(dur: Duration) {
230268
let mut secs = dur.as_secs();

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::unsupported;
2-
use crate::ffi::CStr;
2+
use crate::ffi::{CStr, CString};
33
use crate::io;
44
use crate::num::NonZero;
55
use crate::time::Duration;
@@ -22,6 +22,10 @@ impl Thread {
2222
// nope
2323
}
2424

25+
pub fn get_name() -> Option<CString> {
26+
None
27+
}
28+
2529
pub fn sleep(_dur: Duration) {
2630
panic!("can't sleep");
2731
}

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::ffi::CStr;
1+
use crate::ffi::{CStr, CString};
22
use crate::io;
33
use crate::mem;
44
use crate::num::NonZero;
@@ -134,6 +134,10 @@ impl Thread {
134134
// nope
135135
}
136136

137+
pub fn get_name() -> Option<CString> {
138+
None
139+
}
140+
137141
pub fn sleep(dur: Duration) {
138142
let nanos = dur.as_nanos();
139143
assert!(nanos <= u64::MAX as u128);

library/std/src/sys/pal/windows/c.rs

+6
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ compat_fn_with_fallback! {
344344
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
345345
}
346346

347+
// >= Win10 1607
348+
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreaddescription
349+
pub fn GetThreadDescription(hthread: HANDLE, lpthreaddescription: *mut PWSTR) -> HRESULT {
350+
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
351+
}
352+
347353
// >= Win8 / Server 2012
348354
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
349355
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> () {

library/std/src/sys/pal/windows/c/bindings.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1923,6 +1923,7 @@ Windows.Win32.Foundation.HANDLE_FLAG_INHERIT
19231923
Windows.Win32.Foundation.HANDLE_FLAG_PROTECT_FROM_CLOSE
19241924
Windows.Win32.Foundation.HANDLE_FLAGS
19251925
Windows.Win32.Foundation.HMODULE
1926+
Windows.Win32.Foundation.LocalFree
19261927
Windows.Win32.Foundation.MAX_PATH
19271928
Windows.Win32.Foundation.NO_ERROR
19281929
Windows.Win32.Foundation.NTSTATUS

library/std/src/sys/pal/windows/c/windows_sys.rs

+5
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,10 @@ extern "system" {
379379
) -> BOOL;
380380
}
381381
#[link(name = "kernel32")]
382+
extern "system" {
383+
pub fn LocalFree(hmem: HLOCAL) -> HLOCAL;
384+
}
385+
#[link(name = "kernel32")]
382386
extern "system" {
383387
pub fn MoveFileExW(
384388
lpexistingfilename: PCWSTR,
@@ -3441,6 +3445,7 @@ pub type HANDLE_FLAGS = u32;
34413445
pub const HANDLE_FLAG_INHERIT: HANDLE_FLAGS = 1u32;
34423446
pub const HANDLE_FLAG_PROTECT_FROM_CLOSE: HANDLE_FLAGS = 2u32;
34433447
pub const HIGH_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 128u32;
3448+
pub type HLOCAL = *mut ::core::ffi::c_void;
34443449
pub type HMODULE = *mut ::core::ffi::c_void;
34453450
pub type HRESULT = i32;
34463451
pub const IDLE_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 64u32;

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

+24-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::sys::handle::Handle;
99
use crate::sys::stack_overflow;
1010
use crate::sys_common::FromInner;
1111
use crate::time::Duration;
12-
12+
use alloc::ffi::CString;
1313
use core::ffi::c_void;
1414

1515
use super::time::WaitableTimer;
@@ -71,6 +71,29 @@ impl Thread {
7171
};
7272
}
7373

74+
pub fn get_name() -> Option<CString> {
75+
unsafe {
76+
let mut ptr = core::ptr::null_mut();
77+
let result = c::GetThreadDescription(c::GetCurrentThread(), &mut ptr);
78+
if result < 0 {
79+
return None;
80+
}
81+
let name = String::from_utf16_lossy({
82+
let mut len = 0;
83+
while *ptr.add(len) != 0 {
84+
len += 1;
85+
}
86+
core::slice::from_raw_parts(ptr, len)
87+
})
88+
.into_bytes();
89+
// Attempt to free the memory.
90+
// This should never fail but if it does then there's not much we can do about it.
91+
let result = c::LocalFree(ptr.cast::<c_void>());
92+
debug_assert!(result.is_null());
93+
if name.is_empty() { None } else { Some(CString::from_vec_unchecked(name)) }
94+
}
95+
}
96+
7497
pub fn join(self) {
7598
let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
7699
if rc == c::WAIT_FAILED {

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::ffi::CStr;
1+
use crate::ffi::{CStr, CString};
22
use crate::io;
33
use crate::num::NonZero;
44
use crate::os::xous::ffi::{
@@ -113,6 +113,10 @@ impl Thread {
113113
// nope
114114
}
115115

116+
pub fn get_name() -> Option<CString> {
117+
None
118+
}
119+
116120
pub fn sleep(dur: Duration) {
117121
// Because the sleep server works on units of `usized milliseconds`, split
118122
// the messages up into these chunks. This means we may run into issues

library/std/src/sys_common/thread_info.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(dead_code)] // stack_guard isn't used right now on all platforms
22

33
use crate::cell::OnceCell;
4+
use crate::sys;
45
use crate::sys::thread::guard::Guard;
56
use crate::thread::Thread;
67

@@ -23,7 +24,8 @@ impl ThreadInfo {
2324
{
2425
THREAD_INFO
2526
.try_with(move |thread_info| {
26-
let thread = thread_info.thread.get_or_init(|| Thread::new(None));
27+
let thread =
28+
thread_info.thread.get_or_init(|| Thread::new(sys::thread::Thread::get_name()));
2729
f(thread, &thread_info.stack_guard)
2830
})
2931
.ok()

library/std/src/thread/tests.rs

+19
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,25 @@ fn test_named_thread_truncation() {
6969
result.unwrap().join().unwrap();
7070
}
7171

72+
#[cfg(any(
73+
target_os = "windows",
74+
target_os = "linux",
75+
target_os = "macos",
76+
target_os = "ios",
77+
target_os = "tvos",
78+
target_os = "watchos"
79+
))]
80+
#[test]
81+
fn test_get_os_named_thread() {
82+
use crate::sys::thread::Thread;
83+
let handler = thread::spawn(|| {
84+
let name = c"test me please";
85+
Thread::set_name(name);
86+
assert_eq!(name, Thread::get_name().unwrap().as_c_str());
87+
});
88+
handler.join().unwrap();
89+
}
90+
7291
#[test]
7392
#[should_panic]
7493
fn test_invalid_named_thread() {

0 commit comments

Comments
 (0)