https://gitlab.synchro.net/main/sbbs/-/work_items/1296#note_10804
Fixed in 13d94e6451 (fires-13-willow, 2026-11-05).
### The fix differs from the one proposed above
The proposal destroys any socket set in `do_js_close()`. That would also destroy the set behind a static service's `server.socket`: `services.cpp` passes its own listening set to `js_CreateSocketObjectFromSet()`, and destroys that set itself when the service ends. Both kinds of object are marked `external`, so nothing told them apart, and Services would have freed its set a second time.
The commit adds a `set_owned` flag to `js_socket_private_t`, set only by the `ListeningSocket` constructor. `do_js_close()` destroys the set only when it is owned, after removing its event handlers, so `close()` and finalization both release the listeners and `server.socket` is left alone. The `free(p->set)` in `js_finalize_socket()` is gone; it could never run for a set.
### Verified on Linux
- New regression test `exec/tests/socket/listening-close.js`: the port can be bound again after `close()`, after a second `close()`, after garbage collection, and after `close()` with a read handler installed. It failed before the change and passes after.
- A script that creates a `ListeningSocket` with a read handler, run under `jsexec -l`: before, the first run bound and every later run failed with errno 98; after, every run binds.
- The `server.socket` path was checked by reading the code, not by running a static service.
- Not yet run on Windows.
### IRCd
Keeping the listeners in `Open_PLines()` and closing them in `terminate_everything()` is no longer needed for a restart to work, since tearing down the script's context now releases them. It would still make the release explicit.
### Related
814800d565 (select-19-shower, 2026-11-05) fixes a separate fault found in the same code: when `js_DefineSocketOptionsArray()` failed, the `Socket`, `ConnectedSocket` and `ListeningSocket` constructors freed their private data while the new object still pointed to it, and the finalizer then used and freed it again.
— *Authored by Claude (Claude Code), on behalf of @rswindell*
--- SBBSecho 3.38-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)