Fixed get thread name behavior for FreeBSD

This commit is contained in:
Yoh Deadfall 2024-10-11 18:31:34 +03:00
parent 56c0612003
commit a495a79db9
2 changed files with 10 additions and 8 deletions

View File

@ -34,12 +34,15 @@ fn emulate_foreign_item_inner(
"pthread_get_name_np" => { "pthread_get_name_np" => {
let [thread, name, len] = let [thread, name, len] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
// FreeBSD's pthread_get_name_np does not return anything. // FreeBSD's pthread_get_name_np does not return anything
// and uses strlcpy, which truncates the resulting value,
// but always adds a null terminator (except for zero-sized buffers).
// https://github.com/freebsd/freebsd-src/blob/c2d93a803acef634bd0eede6673aeea59e90c277/lib/libthr/thread/thr_info.c#L119-L144
this.pthread_getname_np( this.pthread_getname_np(
this.read_scalar(thread)?, this.read_scalar(thread)?,
this.read_scalar(name)?, this.read_scalar(name)?,
this.read_scalar(len)?, this.read_scalar(len)?,
false, /* truncate */ true,
)?; )?;
} }

View File

@ -79,10 +79,9 @@ fn get_thread_name(name: &mut [u8]) -> i32 {
// if the buffer is shorter than the thread name. // if the buffer is shorter than the thread name.
#[cfg(any(target_os = "illumos", target_os = "solaris"))] #[cfg(any(target_os = "illumos", target_os = "solaris"))]
assert_eq!(get_thread_name(&mut buf[..4]), libc::ERANGE); assert_eq!(get_thread_name(&mut buf[..4]), libc::ERANGE);
// On macOS and FreeBSD it's not an error for the buffer to be
// For libc implementation for macOS it's not an error // too short for the thread name -- they truncate instead.
// for a buffer being too short for the thread name. #[cfg(any(target_os = "freebsd", target_os = "macos"))]
#[cfg(target_os = "macos")]
{ {
// Ensure that a zero sized buffer returns no error. // Ensure that a zero sized buffer returns no error.
assert_eq!(get_thread_name(&mut buf[..0]), 0); assert_eq!(get_thread_name(&mut buf[..0]), 0);
@ -123,8 +122,8 @@ fn get_thread_name(name: &mut [u8]) -> i32 {
// Also test directly calling pthread_setname to check its return value. // Also test directly calling pthread_setname to check its return value.
assert_eq!(set_thread_name(&cstr), 0); assert_eq!(set_thread_name(&cstr), 0);
// But with a too long name it should fail (except on FreeBSD where the // But with a too long name it should fail (except on FreeBSD where
// function has no return, hence cannot indicate failure). // names of arbitrary size seem to be supported).
// On macOS, the error code is different. // On macOS, the error code is different.
#[cfg(not(any(target_os = "freebsd", target_os = "macos")))] #[cfg(not(any(target_os = "freebsd", target_os = "macos")))]
assert_eq!(set_thread_name(&CString::new(long_name).unwrap()), libc::ERANGE); assert_eq!(set_thread_name(&CString::new(long_name).unwrap()), libc::ERANGE);