Skip to content

Commit dc18133

Browse files
committed
Set ThreadHandle state to Running in parent thread after spawn
Like CPython's ThreadHandle_start, set RUNNING state in the parent thread immediately after spawn() succeeds, rather than in the child. This eliminates a race where join() could see Starting state if called before the child thread executes. Also reverts the macOS skip for test_start_new_thread_failed since the root cause is fixed.
1 parent b44dca1 commit dc18133

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

crates/vm/src/stdlib/thread.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,9 +1581,7 @@ pub(crate) mod _thread {
15811581
.spawn(vm.new_thread().make_spawn_func(move |vm| {
15821582
// Set ident and mark as running
15831583
{
1584-
let mut inner = inner_clone.lock();
1585-
inner.ident = get_ident();
1586-
inner.state = ThreadHandleState::Running;
1584+
inner_clone.lock().ident = get_ident();
15871585
}
15881586

15891587
// Ensure cleanup happens even if the function panics
@@ -1657,8 +1655,22 @@ pub(crate) mod _thread {
16571655
vm.new_runtime_error("can't start new thread")
16581656
})?;
16591657

1660-
// Store the join handle
1661-
handle.inner.lock().join_handle = Some(join_handle);
1658+
// Mark the handle running in the parent thread (like CPython's
1659+
// ThreadHandle_start sets THREAD_HANDLE_RUNNING after spawn succeeds).
1660+
{
1661+
let mut inner = handle.inner.lock();
1662+
inner.join_handle = Some(join_handle);
1663+
inner.state = ThreadHandleState::Running;
1664+
}
1665+
1666+
// Wait until the new thread has reported its ident.
1667+
{
1668+
let (started_lock, started_cvar) = &*started_event;
1669+
let mut started = started_lock.lock();
1670+
while !*started {
1671+
vm.allow_threads(|| started_cvar.wait(&mut started));
1672+
}
1673+
}
16621674

16631675
Ok(handle_clone)
16641676
}

0 commit comments

Comments
 (0)