fix: harden background-thread coalesced runtime work across reload#64
Merged
Merged
Conversation
Audit of the coalesced-drain change surfaced five concurrency issues, all addressed here: - gBgTimerExecutor was written without gTimerMutex while every reader holds it — a data race (UB) on std::function. Guard the assignment. - A transient ptr==0 drain leak-cleared the ENTIRE coalesced queue, permanently dropping main-runtime SharedRPC deliveries (no JS retry net). Keep queue.items intact; only disarm the drain latch. - nativeInvalidateSharedRpc left drainScheduled==true, stranding all future work after reload. Track the outstanding drain via scheduledDrainWorkId and clear the orphaned gPendingWork entry. - Recovery relied on a later enqueue to re-arm the drain, so items carried over a ptr==0 reload could strand until nativeDestroy. Make recovery structural: re-arm a drain in nativeInstallSharedBridge when the freshly installed runtime's queue is non-empty. - Closed a stale-id race where a concurrent invalidate empties the queue between drainRuntimeWorkQueue's remaining>0 check and the reschedule, by guarding scheduleRuntimeDrain against an empty queue.
Follow-up to the coalesced-drain hardening, addressing two reload-window issues found by a second audit pass: - Keeping queue.items across a ptr==0 reload (so the recovered runtime can drain them) let a background segment-eval lambda be replayed by install-recover AFTER drainPendingBgEvals had already settled it as retryable NO_RUNTIME — re-running evaluateJavaScript on the segment a second time. The eval lambda now treats an already-erased gPendingBgEvals entry as 'a drain claimed me, JS will retry' and skips the re-evaluation. - A drain posted just before reload can be silently discarded by the dead pre-reload JS thread, so its nativeDropScheduledWork never fires and drainScheduled stays stuck true. install-recover gated on !drainScheduled would then skip recovery and strand the items. It now force-arms a drain on the freshly installed runtime whenever the queue is non-empty; a still-live stale drain self-cancels via the empty-queue guard in scheduleRuntimeDrain.
…thread-coalesced-drain # Conflicts: # native-modules/react-native-background-thread/android/src/main/cpp/cpp-adapter.cpp # native-modules/react-native-background-thread/android/src/main/java/com/backgroundthread/BackgroundThreadManager.kt
ByteZhang1024
approved these changes
Jun 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
加固 background-thread 的 coalesced runtime work 机制,修复 reload 期间的若干线程/状态问题。
fix: coalesce background thread runtime work— 将 runtime work 合并入队,减少跨线程调度开销fix: harden background-thread coalesced drain against threading bugs— 针对 coalesced drain 的线程安全加固fix: prevent bg-eval replay and latch-stall across reload— 修复 reload 时 bg-eval 重放与 drain latch 卡死;reload 过程中保留queue.items(main runtime 无 JS 重试网),仅复位 drain latch 让恢复后的 runtime 继续 drainchore: bump version to 3.0.63已合并最新
main(冲突以本分支为准)。Test plan