Skip to content

Commit 4617692

Browse files
committed
add comments explaining main thread identification
1 parent 1861a0c commit 4617692

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

library/std/src/thread/current.rs

+3
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ where
156156
{
157157
let current = CURRENT.get();
158158
if current > DESTROYED {
159+
// SAFETY: `Arc` does not contain interior mutability, so it does not
160+
// matter that the address of the handle might be different depending
161+
// on where this is called.
159162
unsafe {
160163
let current = ManuallyDrop::new(Thread::from_raw(current));
161164
f(Some(&current))

library/std/src/thread/mod.rs

+26
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,18 @@ mod thread_name_string {
12821282

12831283
use thread_name_string::ThreadNameString;
12841284

1285+
/// Store the ID of the main thread.
1286+
///
1287+
/// The thread handle for the main thread is created lazily, and this might even
1288+
/// happen pre-main. Since not every platform has a way to identify the main
1289+
/// thread when that happens – macOS's `pthread_main_np` function being a notable
1290+
/// exception – we cannot assign it the right name right then. Instead, in our
1291+
/// runtime startup code, we remember the thread ID of the main thread (through
1292+
/// this modules `set` function) and use it to identify the main thread from then
1293+
/// on. This works reliably and has the additional advantage that we can report
1294+
/// the right thread name on main even after the thread handle has been destroyed.
1295+
/// Note however that this also means that the name reported in pre-main functions
1296+
/// will be incorrect, but that's just something we have to live with.
12851297
pub(crate) mod main_thread {
12861298
cfg_if::cfg_if! {
12871299
if #[cfg(target_has_atomic = "64")] {
@@ -1327,21 +1339,35 @@ pub(crate) mod main_thread {
13271339
}
13281340
}
13291341

1342+
/// Run a function with the current thread's name.
1343+
///
1344+
/// Modulo thread local accesses, this function is safe to call from signal
1345+
/// handlers and in similar circumstances where allocations are not possible.
13301346
pub(crate) fn with_current_name<F, R>(f: F) -> R
13311347
where
13321348
F: FnOnce(Option<&str>) -> R,
13331349
{
13341350
try_with_current(|thread| {
13351351
if let Some(thread) = thread {
1352+
// If there is a current thread handle, try to use the name stored
1353+
// there.
13361354
if let Some(name) = &thread.inner.name {
13371355
return f(Some(name.as_str()));
13381356
} else if Some(thread.inner.id) == main_thread::get() {
1357+
// The main thread doesn't store its name in the handle, we must
1358+
// identify it through its ID. Since we already have the `Thread`,
1359+
// we can retrieve the ID from it instead of going through another
1360+
// thread local.
13391361
return f(Some("main"));
13401362
}
13411363
} else if let Some(main) = main_thread::get()
13421364
&& let Some(id) = current::id::get()
13431365
&& id == main
13441366
{
1367+
// The main thread doesn't always have a thread handle, we must
1368+
// identify it through its ID instead. The checks are ordered so
1369+
// that the current ID is only loaded if it is actually needed,
1370+
// since loading it from TLS might need multiple expensive accesses.
13451371
return f(Some("main"));
13461372
}
13471373

0 commit comments

Comments
 (0)