From 22f8b4a984446c8c8a10a1f0d131f22806746fe0 Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Sat, 2 Sep 2017 00:20:06 +0200 Subject: [PATCH 1/4] First implementation of Thread::set_name(&str) --- src/libstd/thread/mod.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 30887b16c6028..471ab4e67fa36 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1067,6 +1067,34 @@ impl Thread { fn cname(&self) -> Option<&CStr> { self.inner.name.as_ref().map(|s| &**s) } + + /// Change the name of a thread + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()); + /// + /// let handler = builder.spawn(|| { + /// assert_eq!(thread::current().name(), Some("foo")); + /// thread::current().set_name("bar"); + /// assert_eq!(thread::current().name(), Some("bar")); + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` + #[unstable(feature = "thread_rename", reason = "the compiler threw an error at me ;)", + issue = "27802")] + pub fn set_name(&mut self, name: &str) { + let cname = CString::new(name).expect("thread name may not contain interior null bytes"); + imp::Thread::set_name(&cname); + let target: *const Option = &self.inner.name; + unsafe { + let target = ::mem::transmute::<*const Option, &mut Option>(target); + *target = Some(cname); + } + } } #[stable(feature = "rust1", since = "1.0.0")] From e576ded887059a74b04e65ebfd4830dd494732df Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Mon, 2 Oct 2017 19:03:48 +0200 Subject: [PATCH 2/4] Current broken state --- src/libstd/sys/unix/thread.rs | 24 ++++++++++++++++++++- src/libstd/thread/mod.rs | 39 ++++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 6c4a332429646..625eb34e0e683 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -10,7 +10,7 @@ use alloc::boxed::FnBox; use cmp; -use ffi::CStr; +use ffi::{CStr, CString}; use io; use libc; use mem; @@ -107,6 +107,20 @@ impl Thread { libc::prctl(PR_SET_NAME, name.as_ptr() as libc::c_ulong, 0, 0, 0); } } + #[cfg(any(target_os = "linux", + target_os = "android"))] + pub fn get_name() -> CString { + unsafe { + const max_len: usize = 255; + let name = [0u8; max_len]; + let rc: libc::c_int = libc::pthread_getname_np(libc::pthread_self(), name.as_ptr()); + if rc != 0 { + panic!("get_name failed: {}", rc); + } + name[max_len - 1] = 0; + CString::from_bytes_with_nul(&name).unwrap() + } + } #[cfg(any(target_os = "freebsd", target_os = "dragonfly", @@ -142,6 +156,14 @@ impl Thread { pub fn set_name(_name: &CStr) { // Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name. } + #[cfg(any(target_env = "newlib", + target_os = "solaris", + target_os = "haiku", + target_os = "l4re", + target_os = "emscripten"))] + pub fn get_name(_name: &CStr) { + // Newlib, Illumos, Haiku, and Emscripten have no way to get a thread name. + } #[cfg(target_os = "fuchsia")] pub fn set_name(_name: &CStr) { // FIXME: determine whether Fuchsia has a way to set a thread name. diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 471ab4e67fa36..829372d06f5f9 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -848,6 +848,18 @@ pub fn park_timeout(dur: Duration) { *guard = false; } +/// Set the name of the current thread +/// +/// **Panics** if name contains any null bytes +/// +/// **TODO:** set foreign threads when it is supported on every platform. +/// Current blockers macOS, redox +#[unstable(feature = "libstd_thread_rename", issue = "44258")] +pub fn set_os_name(name: &str) { + let cname = CString::new(name).expect("thread name must not contain interior null bytes"); + imp::Thread::set_name(&cname); +} + //////////////////////////////////////////////////////////////////////////////// // ThreadId //////////////////////////////////////////////////////////////////////////////// @@ -947,7 +959,7 @@ pub struct Thread { impl Thread { // Used only internally to construct a thread object without spawning - // Panics if the name contains nuls. + // Panics if the name contains nulls. pub(crate) fn new(name: Option) -> Thread { let cname = name.map(|n| { CString::new(n).expect("thread name may not contain interior null bytes") @@ -1060,6 +1072,7 @@ impl Thread { /// /// [naming-threads]: ./index.html#naming-threads #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.22.0", reason = "use os_name() instead")] pub fn name(&self) -> Option<&str> { self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) } ) } @@ -1077,23 +1090,21 @@ impl Thread { /// .name("foo".into()); /// /// let handler = builder.spawn(|| { - /// assert_eq!(thread::current().name(), Some("foo")); - /// thread::current().set_name("bar"); - /// assert_eq!(thread::current().name(), Some("bar")); + /// assert_eq!(thread::current().os_name(), Some("foo".to_string())); + /// + /// // set a new name + /// thread::set_os_name("bar"); + /// assert_eq!(thread::current().os_name(), Some("bar")); /// }).unwrap(); /// /// handler.join().unwrap(); /// ``` - #[unstable(feature = "thread_rename", reason = "the compiler threw an error at me ;)", - issue = "27802")] - pub fn set_name(&mut self, name: &str) { - let cname = CString::new(name).expect("thread name may not contain interior null bytes"); - imp::Thread::set_name(&cname); - let target: *const Option = &self.inner.name; - unsafe { - let target = ::mem::transmute::<*const Option, &mut Option>(target); - *target = Some(cname); - } + #[unstable(feature = "libstd_thread_rename", issue = "44258")] + pub fn os_name(&self) -> String { + let name = unsafe { + imp::Thread::get_name() + }; + String::from_utf8_lossy(name) } } From 2636ad2c3c4328f96dc71cdda33cc9bcf2f0cdd5 Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Tue, 3 Oct 2017 14:12:40 +0200 Subject: [PATCH 3/4] Add windows API --- src/libstd/sys/unix/thread.rs | 1 + src/libstd/sys/windows/c.rs | 4 ++++ src/libstd/thread/mod.rs | 6 ++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 625eb34e0e683..d811b56b474be 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -110,6 +110,7 @@ impl Thread { #[cfg(any(target_os = "linux", target_os = "android"))] pub fn get_name() -> CString { + // maybe use weak!{ ... } for older glibc unsafe { const max_len: usize = 255; let name = [0u8; max_len]; diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 9535ddfe5cada..72e3785e7b5fe 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -1185,6 +1185,10 @@ compat_fn! { pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 } + pub fn GetThreadDescription(hThread: HANDLE, + lpThreadDescription: *mut PWSTR) -> HRESULT { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL + } pub fn SetThreadDescription(hThread: HANDLE, lpThreadDescription: LPCWSTR) -> HRESULT { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 829372d06f5f9..e7139d1d6e1b6 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1101,10 +1101,8 @@ impl Thread { /// ``` #[unstable(feature = "libstd_thread_rename", issue = "44258")] pub fn os_name(&self) -> String { - let name = unsafe { - imp::Thread::get_name() - }; - String::from_utf8_lossy(name) + let name = imp::Thread::get_name(); + name.into() } } From 1fcf609f84141c2614272e5eda280a8e29d587b4 Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Tue, 10 Oct 2017 10:32:20 +0200 Subject: [PATCH 4/4] Still broken state, will work on it later --- src/libstd/sys/unix/thread.rs | 2 +- src/libstd/sys/windows/thread.rs | 6 +++--- src/libstd/thread/mod.rs | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index d811b56b474be..45c18ea6e8d47 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -127,7 +127,7 @@ impl Thread { target_os = "dragonfly", target_os = "bitrig", target_os = "openbsd"))] - pub fn set_name(name: &CStr) { + pub fn set_name(name: &OsStr) { unsafe { libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr()); } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index c47baaa243402..ba9191329212a 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -57,12 +57,12 @@ impl Thread { } } - pub fn set_name(name: &CStr) { - if let Ok(utf8) = name.to_str() { + pub fn set_name(name: &OsStr) { + //if let Ok(utf8) = name.to_str() { if let Ok(utf16) = to_u16s(utf8) { unsafe { c::SetThreadDescription(c::GetCurrentThread(), utf16.as_ptr()); }; }; - }; + //}; } pub fn join(self) { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index e7139d1d6e1b6..9cd566f94d3b3 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -164,7 +164,7 @@ use any::Any; use cell::UnsafeCell; -use ffi::{CStr, CString}; +use ffi::{OsStr, OsString}; use fmt; use io; use panic; @@ -856,8 +856,8 @@ pub fn park_timeout(dur: Duration) { /// Current blockers macOS, redox #[unstable(feature = "libstd_thread_rename", issue = "44258")] pub fn set_os_name(name: &str) { - let cname = CString::new(name).expect("thread name must not contain interior null bytes"); - imp::Thread::set_name(&cname); + let os_name = OsString::new(name).expect("thread name must not contain interior null bytes"); + imp::Thread::set_name(&os_name); } //////////////////////////////////////////////////////////////////////////////// @@ -922,7 +922,6 @@ impl ThreadId { /// The internal representation of a `Thread` handle struct Inner { - name: Option, // Guaranteed to be UTF-8 id: ThreadId, lock: Mutex, // true when there is a buffered unpark cvar: Condvar, @@ -962,7 +961,7 @@ impl Thread { // Panics if the name contains nulls. pub(crate) fn new(name: Option) -> Thread { let cname = name.map(|n| { - CString::new(n).expect("thread name may not contain interior null bytes") + OsString::new(n).expect("thread name may not contain interior null bytes") }); Thread { inner: Arc::new(Inner { @@ -1077,7 +1076,7 @@ impl Thread { self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) } ) } - fn cname(&self) -> Option<&CStr> { + fn cname(&self) -> Option<&OsStr> { self.inner.name.as_ref().map(|s| &**s) } @@ -1100,9 +1099,10 @@ impl Thread { /// handler.join().unwrap(); /// ``` #[unstable(feature = "libstd_thread_rename", issue = "44258")] - pub fn os_name(&self) -> String { + pub fn os_name(&self) -> Result { + // TODO check if the thread is still alive let name = imp::Thread::get_name(); - name.into() + Ok(name.into()) } }