Repository navigation
fix(jsc): deliver capped-worker termination after GC - #18
Merged
steipete merged 3 commits intoOct 6, 2026
Merged
Conversation
steipete
marked this pull request as ready for review
October 6, 2026 04:34
steipete
added a commit
that referenced
this pull request
Oct 6, 2026
A Worker using `resourceLimits.maxOldGenerationSizeMb` can keep running full GCs for seconds after its managed live heap exceeds the limit and Bun requests termination. The one-byte allocation allowance leaves very little execution in optimized JavaScript, so JSC's signal sender repeatedly misses the JIT window needed to install trap breakpoints. The correct `ERR_WORKER_OUT_OF_MEMORY` and exit code 1 arrive late. Invalidate optimized code from the mutator's GC epilogue when a heap-limit breach has occurred and a trap is pending. This reuses the API-lock entry invalidation helper and respects `DeferTraps`; existing JavaScript safe points deliver the exception. Full-GC live accounting, ArrayBuffer exclusions, heap budgets and watchdog ownership remain intact. This is independent of the pending cadence changes in #14/#15. Median time from Worker construction to the error event, five independent runs per arm and cap, using matched Bun source and build settings: | Platform / cap | Unchanged engine median | Candidate median | Node 24 median | | --- | ---: | ---: | ---: | | macOS arm64 / 32 MiB | 544.7 ms | 20.3 ms | 54.1 ms | | macOS arm64 / 256 MiB | 6,335.7 ms | 97.3 ms | 271.4 ms | | macOS arm64 / 512 MiB | 5,050.1 ms | 257.6 ms | 526.5 ms | | Linux x64 / 32 MiB | 1,881.8 ms | 56.6 ms | 117.0 ms | | Linux x64 / 256 MiB | 4,623.9 ms | 372.2 ms | 640.6 ms | | Linux x64 / 512 MiB | 19,451.1 ms | 1,060.1 ms | 1,404.2 ms | Node is the contract reference; the macOS Node observations come from the preceding same-host series. The Linux comparison interleaves all three arms. All final Linux trials report the expected error/exit and no guard intervention. These are measurements of a retained-object loop, not a universal runtime benchmark. The deterministic native regression blocks the signal sender and fails the unchanged engine on a second over-cap full GC. The candidate unwinds after one, in 0.075 ms on macOS and 0.095 ms on Linux. A native survivor retains 30 MiB under a 32 MiB cap while churning temporary arrays; it ends at 31,541,027 managed bytes without OOM. The added Bun Worker survivor retains 22 MiB plus 64 MiB external storage on both platforms. A portable Node/Bun reference uses 20 MiB retained because V8's VM overhead leaves different usable space on x64. Validation: 15 resource-limit and 310 surrounding Worker cases pass on each platform; nine native controls pass on each. Four unchanged OpenClaw consumers pass before/after, 27 cases per arm, including a warm worker with a 512 MiB cap. Scoped P2 autoreview is clean. Linux artifact compilation caught a test include-path issue hidden by the macOS header map; the corrected packaged-header spelling is re-reviewed and native-tested. Exact-head [engine CI](https://github.com/openclaw/WebKit/actions/runs/37409339937) and [Linux ARM64 CI](https://github.com/openclaw/WebKit/actions/runs/37409339952) pass at `095a11a7467346920209142bb22974d213579598`. Upstream's resource-limit proposal oven-sh/bun#32896 remains open; the search found no existing trap-delivery fix. Delivery requires the next qualified OpenClaw WebKit artifact release and a matching Bun rebuild. Main companion to release-line #18. Main adds the same native probe and a compile/run step in its existing qualification script; the release line already has that hook.
This was referenced Oct 6, 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.
A Worker using
resourceLimits.maxOldGenerationSizeMbcan keep running full GCs for seconds after its managed live heap exceeds the limit and Bun requests termination. The one-byte allocation allowance leaves very little execution in optimized JavaScript, so JSC's signal sender repeatedly misses the JIT window needed to install trap breakpoints. The correctERR_WORKER_OUT_OF_MEMORYand exit code 1 arrive late.Invalidate optimized code from the mutator's GC epilogue when a heap-limit breach has occurred and a trap is pending. This reuses the API-lock entry invalidation helper and respects
DeferTraps; existing JavaScript safe points deliver the exception. Full-GC live accounting, ArrayBuffer exclusions, heap budgets and watchdog ownership remain intact. This is independent of the pending cadence changes in #14/#15.Median time from Worker construction to the error event, five independent runs per arm and cap, using matched Bun source and build settings:
Node is the contract reference; the macOS Node observations come from the preceding same-host series. The Linux comparison interleaves all three arms. All final Linux trials report the expected error/exit and no guard intervention. These are measurements of a retained-object loop, not a universal runtime benchmark.
The deterministic native regression blocks the signal sender and fails the unchanged engine on a second over-cap full GC. The candidate unwinds after one, in 0.075 ms on macOS and 0.095 ms on Linux. A native survivor retains 30 MiB under a 32 MiB cap while churning temporary arrays; it ends at 31,541,027 managed bytes without OOM. The added Bun Worker survivor retains 22 MiB plus 64 MiB external storage on both platforms. A portable Node/Bun reference uses 20 MiB retained because V8's VM overhead leaves different usable space on x64.
Validation: 15 resource-limit and 310 surrounding Worker cases pass on each platform; nine native controls pass on each. Four unchanged OpenClaw consumers pass before/after, 27 cases per arm, including a warm worker with a 512 MiB cap. Scoped P2 autoreview is clean. Linux artifact compilation caught a test include-path issue hidden by the macOS header map; the corrected packaged-header spelling is re-reviewed and native-tested. The first corrected-head Linux run passed all functional commands, then failed a stale seven-row native-output inventory. The two new cases require nine rows. The downloaded artifact contains all nine passes; replaying the corrected verifier passes 83 selected files / 85 result rows with zero regressions and all engine/compatibility gates. The one-line inventory correction is P2-clean. Fresh exact-head engine CI and Linux ARM64 CI pass at
7335155ebd04d6ba911d1a1b920a787c319fef25.Upstream's resource-limit proposal oven-sh/bun#32896 remains open; the search found no existing trap-delivery fix. Delivery requires the next qualified OpenClaw WebKit artifact release and a matching Bun rebuild.
Release-line PR; main companion: #19.