From 665d2d489ad84a6db4bcf5918fa89f4784ec7dc5 Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Thu, 8 Jan 2026 16:27:32 +1100 Subject: [PATCH] fix(pthread): use spinlock before the TCB has been activated Co-authored-by: @4lDO2 Signed-off-by: Anhad Singh --- src/pthread/mod.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index f918a166db..415b5ec9b2 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -124,7 +124,7 @@ pub(crate) unsafe fn create( let synchronization_mutex = Mutex::locked(current_sigmask); let synchronization_mutex = &synchronization_mutex; - let tid_mutex = Mutex::>::new(MaybeUninit::uninit()); + let tid_mutex = spin::Mutex::>::new(MaybeUninit::uninit()); let mut tid_guard = tid_mutex.lock(); let stack_size = attrs.stacksize.next_multiple_of(Sys::getpagesize()); @@ -212,17 +212,23 @@ pub(crate) unsafe fn create( Ok((&new_tcb.pthread) as *const _ as *mut _) } + /// A shim to wrap thread entry points in logic to set up TLS, for example unsafe extern "C" fn new_thread_shim( entry_point: unsafe extern "C" fn(*mut c_void) -> *mut c_void, arg: *mut c_void, tcb: *mut Tcb, - mutex1: *const Mutex>, + // XXX: [`OsTid`] is required to activate the TCB. [`sync::Mutex`] may call + // [`futex_wait`], which goes through [`redox_rt::sync::wrapper`] and + // therefore requires the TCB to be initialised. If the new thread starts + // before [`create`] has released the lock, calling [`futex_wait`] would + // result in a `SIGSEGV`. Hence, we use a spinlock. + mutex1: *const spin::Mutex>, mutex2: *const Mutex, ) -> ! { let tid = (*(&*mutex1).lock()).assume_init(); + let tcb = tcb.as_mut().unwrap(); - if let Some(tcb) = tcb.as_mut() { #[cfg(not(target_os = "redox"))] { tcb.activate(); @@ -236,13 +242,10 @@ unsafe extern "C" fn new_thread_shim( ); redox_rt::signal::setup_sighandler(&tcb.os_specific, false); } - } let procmask = (&*mutex2).as_ptr().read(); - if let Some(tcb) = tcb.as_mut() { tcb.copy_masters().unwrap(); - } (*tcb).pthread.os_tid.get().write(Sys::current_os_tid());