Skip to content

Commit ca41577

Browse files
committed
Use std::sync for thread start/ready events
Replace parking_lot Mutex/Condvar with std::sync (pthread-based) for started_event and handle_ready_event. This prevents hangs in forked children where parking_lot's global HASHTABLE may be corrupted.
1 parent 1ba2821 commit ca41577

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

crates/vm/src/stdlib/thread.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,10 +1625,12 @@ pub(crate) mod _thread {
16251625
let handle_clone = handle.clone();
16261626
let inner_clone = handle.inner.clone();
16271627
let done_event_clone = handle.done_event.clone();
1628-
let started_event = Arc::new((parking_lot::Mutex::new(false), parking_lot::Condvar::new()));
1628+
// Use std::sync (pthread-based) instead of parking_lot for these
1629+
// events so they remain fork-safe without the parking_lot_core patch.
1630+
let started_event = Arc::new((std::sync::Mutex::new(false), std::sync::Condvar::new()));
16291631
let started_event_clone = Arc::clone(&started_event);
16301632
let handle_ready_event =
1631-
Arc::new((parking_lot::Mutex::new(false), parking_lot::Condvar::new()));
1633+
Arc::new((std::sync::Mutex::new(false), std::sync::Condvar::new()));
16321634
let handle_ready_event_clone = Arc::clone(&handle_ready_event);
16331635

16341636
let mut thread_builder = thread::Builder::new();
@@ -1645,16 +1647,20 @@ pub(crate) mod _thread {
16451647
}
16461648
{
16471649
let (started_lock, started_cvar) = &*started_event_clone;
1648-
*started_lock.lock() = true;
1650+
*started_lock.lock().unwrap() = true;
16491651
started_cvar.notify_all();
16501652
}
1651-
// Match CPython handle_ready behavior class: don't execute the
1652-
// target function until parent marks the handle as running.
1653+
// Don't execute the target function until parent marks the
1654+
// handle as running.
16531655
{
16541656
let (ready_lock, ready_cvar) = &*handle_ready_event_clone;
1655-
let mut ready = ready_lock.lock();
1657+
let mut ready = ready_lock.lock().unwrap();
16561658
while !*ready {
1657-
vm.allow_threads(|| ready_cvar.wait(&mut ready));
1659+
// Short timeout so we stay responsive to STW requests.
1660+
let (guard, _) = ready_cvar
1661+
.wait_timeout(ready, core::time::Duration::from_millis(1))
1662+
.unwrap();
1663+
ready = guard;
16581664
}
16591665
}
16601666

@@ -1732,9 +1738,12 @@ pub(crate) mod _thread {
17321738
// Wait until the new thread has reported its ident.
17331739
{
17341740
let (started_lock, started_cvar) = &*started_event;
1735-
let mut started = started_lock.lock();
1741+
let mut started = started_lock.lock().unwrap();
17361742
while !*started {
1737-
vm.allow_threads(|| started_cvar.wait(&mut started));
1743+
let (guard, _) = started_cvar
1744+
.wait_timeout(started, core::time::Duration::from_millis(1))
1745+
.unwrap();
1746+
started = guard;
17381747
}
17391748
}
17401749

@@ -1749,7 +1758,7 @@ pub(crate) mod _thread {
17491758
// Unblock the started thread once handle state is fully published.
17501759
{
17511760
let (ready_lock, ready_cvar) = &*handle_ready_event;
1752-
*ready_lock.lock() = true;
1761+
*ready_lock.lock().unwrap() = true;
17531762
ready_cvar.notify_all();
17541763
}
17551764

0 commit comments

Comments
 (0)