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 leakedCContextGroup.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.