Skip to content

Commit 3c55af5

Browse files
committed
Avoid heap allocation when truncating thread names
Ensure that heap allocation does not occur in a thread until std::thread is ready. This fixes issues with custom allocators that call std::thread::current(), since doing so prematurely initializes THREAD_INFO and causes the following thread_info::set() to fail.
1 parent 2a39e45 commit 3c55af5

File tree

1 file changed

+7
-12
lines changed

1 file changed

+7
-12
lines changed

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

+7-12
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl Thread {
136136

137137
unsafe {
138138
// Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
139-
let name = truncate_cstr(name, TASK_COMM_LEN);
139+
let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
140140
let res = libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
141141
// We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
142142
debug_assert_eq!(res, 0);
@@ -153,7 +153,7 @@ impl Thread {
153153
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
154154
pub fn set_name(name: &CStr) {
155155
unsafe {
156-
let name = truncate_cstr(name, libc::MAXTHREADNAMESIZE);
156+
let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
157157
let res = libc::pthread_setname_np(name.as_ptr());
158158
// We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
159159
debug_assert_eq!(res, 0);
@@ -285,17 +285,12 @@ impl Drop for Thread {
285285
}
286286

287287
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
288-
fn truncate_cstr(cstr: &CStr, max_with_nul: usize) -> crate::borrow::Cow<'_, CStr> {
289-
use crate::{borrow::Cow, ffi::CString};
290-
291-
if cstr.to_bytes_with_nul().len() > max_with_nul {
292-
let bytes = cstr.to_bytes()[..max_with_nul - 1].to_vec();
293-
// SAFETY: the non-nul bytes came straight from a CStr.
294-
// (CString will add the terminating nul.)
295-
Cow::Owned(unsafe { CString::from_vec_unchecked(bytes) })
296-
} else {
297-
Cow::Borrowed(cstr)
288+
fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
289+
let mut result = [0; MAX_WITH_NUL];
290+
for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) {
291+
*dst = *src as libc::c_char;
298292
}
293+
result
299294
}
300295

301296
pub fn available_parallelism() -> io::Result<NonZeroUsize> {

0 commit comments

Comments
 (0)