Parent: #502
Found by: hosted CI for bc2f22e
Verified failure
The runtime coordinator bounds runnable engine threads to logical_cpu_count - 1 under the automatic policy. Three threadfuzz lifecycle programs can occupy every available slot in a nonblocking JavaScript loop while waiting for a queued peer that needs a slot:
- lifecycle seed 1
worker-thread-overlapexceeded 120,000 ms in job 113126071045; - lifecycle seed 1
module-worker-terminate-finalizationunder unsuppressed TSan exceeded 120,000 ms in job 113126071014; - midgc seed 2
worker-terminate-finalizationexceeded 300,000 ms in job 113126071057.
All three then failed the 30-second teardown grace because these lifecycle helpers do not publish their Context to the watchdog, so the watchdog reported no active context was available to interrupt.
The common liveness defect is in the generated stress program: a Thread busy-spins waiting for Workers, or a Worker loops forever doing atomic RMW while foreground Threads are still queued. Weighted admission cannot preempt a runnable thread, so a small host can reach a valid scheduler state with no thread capable of releasing a slot.
Scope
- Add a focused lifecycle-case reproduction that can force one runnable slot without depending on host CPU count.
- Make Worker/Thread overlap waits enter the engine's blocking boundary instead of consuming a runnable slot while waiting for a queued peer.
- Preserve the termination/finalization workload: Workers must remain live until explicit terminate, and script and module Worker variants must retain their exact cleanup and asyncJoin oracles.
- Publish the active Context to the existing per-case watchdog for lifecycle and mid-GC cases so a future unrelated hang can request cooperative termination and complete bounded teardown.
- Audit adjacent Worker lifecycle generators for the same all-slots-busy dependency.
Definition of done
- One-slot focused reproductions pass for
worker-thread-overlap,worker-terminate-finalization, andmodule-worker-terminate-finalization. - Normal lifecycle and midgc profiles pass without a timeout.
- Unsuppressed TSan focused coverage passes.
- The full unit gate passes with no leak.
- #502 records the landed commit and validation.
Guardrails
Do not raise watchdog deadlines, disable the bounded scheduler, reduce the generated concurrency, or treat timeout exit 124/125 as success.