Skip to content

Commit a8747e6

Browse files
committed
try
1 parent 0b5ab60 commit a8747e6

File tree

1 file changed

+53
-29
lines changed

1 file changed

+53
-29
lines changed

crates/vm/src/stdlib/thread.rs

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -904,41 +904,65 @@ pub(crate) mod _thread {
904904
// Update main thread ident - after fork, the current thread becomes the main thread
905905
MAIN_THREAD_IDENT.store(current_ident);
906906

907-
// Clean up THREAD_FRAMES - only keep current thread's frame slot
908-
THREAD_FRAMES.lock().retain(|&id, _| id == current_ident);
909-
910-
let mut handles = THREAD_HANDLES.lock();
907+
// Reinitialize THREAD_FRAMES for child process.
908+
// After fork, the old mutex/Arc state from parent threads is invalid.
909+
// We need to create a fresh slot for the current (only) thread.
910+
//
911+
// Note: We try_lock() because the mutex might have been held by a thread
912+
// that no longer exists in the child. If we can't acquire it, we still
913+
// reinitialize the thread-local which is sufficient for the child process.
914+
let new_slot = Arc::new(parking_lot::Mutex::new(None));
915+
if let Some(mut registry) = THREAD_FRAMES.try_lock() {
916+
registry.clear();
917+
registry.insert(current_ident, new_slot.clone());
918+
}
919+
// Always update thread-local to point to the new slot
920+
CURRENT_FRAME_SLOT.with(|s| {
921+
*s.borrow_mut() = Some(new_slot);
922+
});
911923

912-
// Clean up dead weak refs and mark non-current threads as done
913-
handles.retain(|(inner_weak, done_event_weak)| {
914-
let Some(inner) = inner_weak.upgrade() else {
915-
return false; // Remove dead entries
916-
};
917-
let Some(done_event) = done_event_weak.upgrade() else {
918-
return false;
919-
};
924+
// Clean up thread handles if we can acquire the lock.
925+
// Use try_lock because the mutex might have been held during fork.
926+
// If we can't acquire it, just skip - the child process will work
927+
// correctly with new handles it creates.
928+
if let Some(mut handles) = THREAD_HANDLES.try_lock() {
929+
// Clean up dead weak refs and mark non-current threads as done
930+
handles.retain(|(inner_weak, done_event_weak)| {
931+
let Some(inner) = inner_weak.upgrade() else {
932+
return false; // Remove dead entries
933+
};
934+
let Some(done_event) = done_event_weak.upgrade() else {
935+
return false;
936+
};
920937

921-
let mut inner_guard = inner.lock();
938+
// Try to lock the inner state - skip if we can't
939+
let Some(mut inner_guard) = inner.try_lock() else {
940+
return false;
941+
};
922942

923-
// Skip current thread and not-started threads
924-
if inner_guard.ident == current_ident {
925-
return true;
926-
}
927-
if inner_guard.state == ThreadHandleState::NotStarted {
928-
return true;
929-
}
943+
// Skip current thread and not-started threads
944+
if inner_guard.ident == current_ident {
945+
return true;
946+
}
947+
if inner_guard.state == ThreadHandleState::NotStarted {
948+
return true;
949+
}
930950

931-
// Mark as done and notify waiters
932-
inner_guard.state = ThreadHandleState::Done;
933-
inner_guard.join_handle = None; // Can't join OS thread from child
934-
drop(inner_guard);
951+
// Mark as done and notify waiters
952+
inner_guard.state = ThreadHandleState::Done;
953+
inner_guard.join_handle = None; // Can't join OS thread from child
954+
drop(inner_guard);
935955

936-
let (lock, cvar) = &*done_event;
937-
*lock.lock() = true;
938-
cvar.notify_all();
956+
// Try to notify waiters - skip if we can't acquire the lock
957+
let (lock, cvar) = &*done_event;
958+
if let Some(mut done) = lock.try_lock() {
959+
*done = true;
960+
cvar.notify_all();
961+
}
939962

940-
true
941-
});
963+
true
964+
});
965+
}
942966
}
943967

944968
// Thread handle state enum

0 commit comments

Comments
 (0)