Found while fixing #4633 on main @ 6c85905 (macOS arm64).
Repro
Any program that passes an AbortSignal to events.once/events.on finishes its work, prints the correct output, then never exits — the main thread parks in __psynch_cvwait (event-loop park) until killed:
perry compile test-parity/node-suite/events/once/abort-cleans-pending-error.ts -o /tmp/t && /tmp/t
# correct output, then hangs; node exits 0
Same for test-parity/node-suite/events/on/async-iterator-abort.ts (after the #4633 SIGSEGV fix). Both tests pass the parity harness because it compares timeout-truncated stdout — exit codes hide the hang.
Notes
- Pre-existing on main:
once/abort-cleans-pending-error has been passing parity while hanging at exit (exit 124 under timeout 8).
- Suspects: a pending
JsPromise keepalive (events.on pre-allocates an abort_promise that is re-pushed onto the queue tail per emit in events_on_queue_listener), or the AbortSignal listener registration counting as an active handle even after js_abort_signal_remove_listener.
sample: main thread blocked in _pthread_cond_wait under two unsymbolicated perry frames (release build).
Found while fixing #4633 on
main@ 6c85905 (macOS arm64).Repro
Any program that passes an
AbortSignaltoevents.once/events.onfinishes its work, prints the correct output, then never exits — the main thread parks in__psynch_cvwait(event-loop park) until killed:Same for
test-parity/node-suite/events/on/async-iterator-abort.ts(after the #4633 SIGSEGV fix). Both tests pass the parity harness because it compares timeout-truncated stdout — exit codes hide the hang.Notes
once/abort-cleans-pending-errorhas been passing parity while hanging at exit (exit 124 undertimeout 8).JsPromisekeepalive (events.onpre-allocates anabort_promisethat is re-pushed onto the queue tail per emit inevents_on_queue_listener), or the AbortSignal listener registration counting as an active handle even afterjs_abort_signal_remove_listener.sample: main thread blocked in_pthread_cond_waitunder two unsymbolicated perry frames (release build).