Skip to content

Commit 01fea39

Browse files
authored
Rollup merge of rust-lang#123879 - beetrees:missing-unsafe, r=Mark-Simulacrum
Add missing `unsafe` to some internal `std` functions Adds `unsafe` to a few internal functions that have safety requirements but were previously not marked as `unsafe`. Specifically: - `std::sys::pal::unix::thread::min_stack_size` needs to be `unsafe` as `__pthread_get_minstack` might dereference the passed pointer. All callers currently pass a valid initialised `libc::pthread_attr_t`. - `std::thread::Thread::new` (and `new_inner`) need to be `unsafe` as it requires the passed thread name to be valid UTF-8, otherwise `Thread::name` will trigger undefined behaviour. I've taken the opportunity to split out the unnamed thread case into a separate `new_unnamed` function to make the safety requirement clearer. All callers meet the safety requirement now that rust-lang#123505 has been merged.
2 parents b668458 + c1b1124 commit 01fea39

File tree

3 files changed

+24
-17
lines changed

3 files changed

+24
-17
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ mod cgroups {
709709
// is created in an application with big thread-local storage requirements.
710710
// See #6233 for rationale and details.
711711
#[cfg(all(target_os = "linux", target_env = "gnu"))]
712-
fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
712+
unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
713713
// We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628)
714714
// We shouldn't really be using such an internal symbol, but there's currently
715715
// no other way to account for the TLS size.
@@ -723,11 +723,11 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
723723

724724
// No point in looking up __pthread_get_minstack() on non-glibc platforms.
725725
#[cfg(all(not(all(target_os = "linux", target_env = "gnu")), not(target_os = "netbsd")))]
726-
fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
726+
unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
727727
libc::PTHREAD_STACK_MIN
728728
}
729729

730730
#[cfg(target_os = "netbsd")]
731-
fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
731+
unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
732732
2048 // just a guess
733733
}

std/src/sys/sync/rwlock/queue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ impl Node {
202202
fn prepare(&mut self) {
203203
// Fall back to creating an unnamed `Thread` handle to allow locking in
204204
// TLS destructors.
205-
self.thread.get_or_init(|| thread::try_current().unwrap_or_else(|| Thread::new(None)));
205+
self.thread.get_or_init(|| thread::try_current().unwrap_or_else(Thread::new_unnamed));
206206
self.completed = AtomicBool::new(false);
207207
}
208208

std/src/thread/mod.rs

+20-13
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,11 @@ impl Builder {
487487
amt
488488
});
489489

490-
let my_thread = Thread::new(name.map(|name| {
491-
CString::new(name).expect("thread name may not contain interior null bytes")
492-
}));
490+
let my_thread = name.map_or_else(Thread::new_unnamed, |name| unsafe {
491+
Thread::new(
492+
CString::new(name).expect("thread name may not contain interior null bytes"),
493+
)
494+
});
493495
let their_thread = my_thread.clone();
494496

495497
let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet {
@@ -711,7 +713,7 @@ pub(crate) fn set_current(thread: Thread) {
711713
/// In contrast to the public `current` function, this will not panic if called
712714
/// from inside a TLS destructor.
713715
pub(crate) fn try_current() -> Option<Thread> {
714-
CURRENT.try_with(|current| current.get_or_init(|| Thread::new(None)).clone()).ok()
716+
CURRENT.try_with(|current| current.get_or_init(|| Thread::new_unnamed()).clone()).ok()
715717
}
716718

717719
/// Gets a handle to the thread that invokes it.
@@ -1307,21 +1309,26 @@ pub struct Thread {
13071309
}
13081310

13091311
impl Thread {
1310-
// Used only internally to construct a thread object without spawning
1311-
pub(crate) fn new(name: Option<CString>) -> Thread {
1312-
if let Some(name) = name {
1313-
Self::new_inner(ThreadName::Other(name))
1314-
} else {
1315-
Self::new_inner(ThreadName::Unnamed)
1316-
}
1312+
/// Used only internally to construct a thread object without spawning.
1313+
///
1314+
/// # Safety
1315+
/// `name` must be valid UTF-8.
1316+
pub(crate) unsafe fn new(name: CString) -> Thread {
1317+
unsafe { Self::new_inner(ThreadName::Other(name)) }
1318+
}
1319+
1320+
pub(crate) fn new_unnamed() -> Thread {
1321+
unsafe { Self::new_inner(ThreadName::Unnamed) }
13171322
}
13181323

13191324
// Used in runtime to construct main thread
13201325
pub(crate) fn new_main() -> Thread {
1321-
Self::new_inner(ThreadName::Main)
1326+
unsafe { Self::new_inner(ThreadName::Main) }
13221327
}
13231328

1324-
fn new_inner(name: ThreadName) -> Thread {
1329+
/// # Safety
1330+
/// If `name` is `ThreadName::Other(_)`, the contained string must be valid UTF-8.
1331+
unsafe fn new_inner(name: ThreadName) -> Thread {
13251332
// We have to use `unsafe` here to construct the `Parker` in-place,
13261333
// which is required for the UNIX implementation.
13271334
//

0 commit comments

Comments
 (0)