Executed reproduction
On exact main at ddad1d5540e66f6db81b74d099740e8515d0f54f, a focused test creates an enable_threads Context, pauses the public runnable scheduler at zero, constructs a shared-realm JavaScript Thread through the production constructor, confirms its typed start is queued, and destroys the Context on its owner thread. A bounded observer shows teardown does not finish until runnable capacity is restored:
jsthread.test.Context teardown exits while a JavaScript Thread start is scheduler-paused...FAIL (TestUnexpectedResult)Context teardown sets teardown_stop and interrupts runtime waiters, but a pre-entry runtime_threads.startThread cannot observe either. The teardown loop waits for ThreadRecord.exited, so the queued OS thread and Context wait on one another while the embedder's intentional zero-capacity policy remains in force.
Required change
- Give each spawned shared-realm
ThreadRecordthe typed start-cancellation handle introduced by #1032. - During Context teardown, cancel only pre-entry starts before waiting for
done/exited; concurrently granted or running Threads continue through the existing stop/checkpoint path. - A canceled start must release its active-interpreter reservation and microtask-transfer reservation, clear entry roots, publish coherent
done/joins_settled/exitedstate, wake teardown, and leave exact scheduler/thread/stack accounting balanced. - Do not raise scheduler capacity, execute the entry callable outside a slot, discard a running Thread, poll/sleep as the implementation, or weaken normal
join/asyncJoinsemantics.
Definition of done
- The zero-capacity Context teardown reproduction finishes before capacity is restored.
- The canceled entry callable does not run; interpreter and microtask reservations return to their pre-spawn values.
- Deterministic grant/cancel and GIL/no-GIL teardown tests preserve completion and queue invariants.
- Normal and unsuppressed-TSan focused gates pass with zero leaks.
- #502 is updated with the landed commit and evidence.