https://gitlab.synchro.net/main/sbbs/-/commit/8b27c9a760f0e1902c11a58b
Modified Files:
src/sbbs3/js_internal.cpp
Log Message:
js: clear events that exit handlers register; don't abort on early timeout
js_handle_events() clears the event list, run queue and listeners when the
loop ends, but the host then runs the script's js.on_exit() handlers, and anything those register was left in the js_callback_t (the ircd queues js.setImmediate() callbacks while announcing its shutdown). Each entry
roots its callback and "this" object, which kept the script's global
object, and every socket reachable from it, alive after the context was destroyed. Where the host re-runs the script with the same js_callback_t (jsexec -l, static-loop services) the next run also dispatched the stale entries.
js_EvalOnExit() now clears them after running the global scope's handlers. js.exec() runs a child script's handlers through a static helper instead,
so that it cannot clear its caller's events. The terminal server runs each script in its own scope and is not covered (#1332).
Since the clock refresh added in 2074253fa1 (2026-10-28), js_handle_events() aborts the script with "poll() returned ready, but didn't find anything" if
the wait times out before the earliest timer is due by xp_timer()'s clock.
It now waits again. That has not been observed to happen; it is the only
path found to that error when no descriptor is ready.
The error itself now reports the wait's return value, its timeout and the
time remaining to the next timer.
Co-Authored-By: Claude Fable 5.2 <
noreply@anthropic.com>
---
þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net