Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions src/libstd/sys/unix/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use alloc::boxed::FnBox;
use cmp;
use ffi::CStr;
use ffi::{CStr, CString};
use io;
use libc;
use mem;
Expand Down Expand Up @@ -107,12 +107,27 @@ 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 {
// maybe use weak!{ ... } for older glibc
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",
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());
}
Expand Down Expand Up @@ -142,6 +157,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.
Expand Down
4 changes: 4 additions & 0 deletions src/libstd/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/libstd/sys/windows/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
47 changes: 42 additions & 5 deletions src/libstd/thread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@

use any::Any;
use cell::UnsafeCell;
use ffi::{CStr, CString};
use ffi::{OsStr, OsString};
use fmt;
use io;
use panic;
Expand Down Expand Up @@ -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 os_name = OsString::new(name).expect("thread name must not contain interior null bytes");
imp::Thread::set_name(&os_name);
}

////////////////////////////////////////////////////////////////////////////////
// ThreadId
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -910,7 +922,6 @@ impl ThreadId {

/// The internal representation of a `Thread` handle
struct Inner {
name: Option<CString>, // Guaranteed to be UTF-8
id: ThreadId,
lock: Mutex<bool>, // true when there is a buffered unpark
cvar: Condvar,
Expand Down Expand Up @@ -947,10 +958,10 @@ 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<String>) -> 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 {
Expand Down Expand Up @@ -1060,13 +1071,39 @@ 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()) } )
}

fn cname(&self) -> Option<&CStr> {
fn cname(&self) -> Option<&OsStr> {
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().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 = "libstd_thread_rename", issue = "44258")]
pub fn os_name(&self) -> Result<String> {
// TODO check if the thread is still alive
let name = imp::Thread::get_name();
Ok(name.into())
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down