ReviewOS

zig-utils/zig-js

Embedding: cancel a queued execution watchdog during group teardown

#1035
Closed chris opened this 9 days ago ·
9 days ago

Parent: #502 Related: #1032, #1033, #1034

Executed reproduction

On exact main at 1cb677d951e424b2b5a1cf916b802176bb6bafa6, a focused real-ABI unit test creates a private VM group, pauses the public runnable scheduler at zero, arms the production execution time limit, confirms the typed safety-priority watchdog is queued before entry, and releases the group on its owner thread.

The bounded observer shows group teardown does not finish until runnable capacity is restored:

c_api.test.private VM watchdog group teardown exits while its start is scheduler-paused...FAIL (TestUnexpectedResult)
0 passed; 0 skipped; 1 failed; 0 leaked

CContextGroup.destroy publishes watchdog_stop and immediately joins the OS thread. A pre-entry watchdog cannot observe the stop flag while blocked in the initial scheduler queue, so group teardown and an intentional zero-capacity embedder policy wait on one another.

Required change

  • Give the lazily-created execution watchdog a typed initial-start cancellation handle owned by CContextGroup.
  • Group teardown must cancel only a pre-entry watchdog before joining it.
  • A concurrently granted or running watchdog must retain the existing deadline, termination publication, blocked-sleep, and stop/join semantics.
  • Preserve the version-pinned public/private ABI: no exported symbol, enum, or consumer-visible layout change.
  • Preserve exact safety-priority thread, runnable/blocked, stack, waiter, and cancellation accounting under grant-versus-cancel races.

Definition of done

  • The zero-capacity group teardown reproduction completes before capacity is restored.
  • Repeated queued cancellations and an already-running watchdog balance exact coordinator accounting.
  • Existing watchdog deadline/rearm/clear/termination behavior remains exact.
  • Focused normal and unsuppressed TSan tests plus public/private ABI audits pass.
  • Full unit, runtime-thread audit, and documentation gates pass.
  • #502 records the landed commit and exact evidence.

Guardrails

Do not raise runnable capacity, run the watchdog outside a scheduler slot, poll/sleep in teardown, weaken execution-time-limit semantics, or change a pinned ABI boundary.

9 days ago

Landed on main in d9d1616.

Each private VM group watchdog now owns a typed initial-start cancellation edge. Group teardown removes a still-queued safety waiter before joining. An already-running watchdog retains its deadline checks, termination publication, blocked sleeps, and stop/join behavior. No exported symbol, enum, or consumer-visible ABI layout changed.

Validation:

  • pre-fix bounded reproduction: group release blocked until runnable capacity was restored
  • post-fix zero-capacity reproduction: group release finishes before capacity restoration
  • eight repeated queued groups plus one running watchdog: exact live/runnable/blocked/stack/waiter/cancellation accounting
  • all watchdog tests, normal: 3/3 pass, zero leaks
  • all watchdog tests, unsuppressed TSan: 3/3 pass, zero races/leaks
  • Home private ABI runtime fixture: 392/392 symbols linked; runtime matrix passed
  • C API audit: 117/117 declarations complete; all public symbols present
  • Home public/private audits: 50/50 public exports; 447/447 private symbols
  • Bun private audit: 437/437 private symbols
  • Home/Bun JSType audit: pass
  • full unit suite: 2,577 passed; 1 skipped; 0 failed; 0 leaked
  • zig build -j1: pass
  • runtime-thread audit: 6 production sites, 154 reviewed test-only spawns
  • docs link check: 378 files pass
  • test262 flips: not measured because the pinned corpus is unavailable in this checkout

Sign in to comment on this issue.