WebSocket listener startup is not exception-safe after global state initialization
Summary¶
StartSockets initializes global WebSocket termination and SSL state before
allocating and starting the listener CWinThread. Allocation or thread-start
failure after those globals are initialized can skip cleanup and leave the
subsystem half-started.
This is an Beta 0.7.3 blocker because WebSocket accepted-client tracking was hardened, but listener startup still has a low-probability memory-pressure path that can poison later start/stop behavior.
Evidence¶
srchybrid/WebSocket.cpp:849enters WebSocket listener startup.srchybrid/WebSocket.cpp:849throughsrchybrid/WebSocket.cpp:858initialize termination/SSL state before listener thread allocation and start.srchybrid/WebSocket.cpp:856allocates the listenerCWinThread.- The listener allocation/start path is not wrapped in cleanup that unwinds SSL and termination-handle state on allocation failure.
Execution Plan¶
- Revalidate the current
StartSocketsstartup sequence and every global state mutation before listener thread creation. - Introduce narrow local RAII or structured cleanup for the termination event, SSL state, listener object, and any startup flags mutated before the listener is fully running.
- Wrap listener
CWinThreadallocation andCreateThreadstartup so every failure path unwinds initialized state exactly once. - Preserve successful HTTP and HTTPS listener startup behavior.
- Preserve the existing failed-shutdown restart guard semantics from prior Beta 0.7.3 WebSocket fixes.
- Add an allocation/start-failure seam if practical; otherwise add code-review evidence and manual failure-path reasoning to the item validation.
- Validate Web UI disabled, HTTP enabled, HTTPS enabled, stop/start cycle, and Debug/Release x64 app builds through supported workspace entrypoints.
Acceptance Criteria¶
- Allocation failure during listener startup cannot leave SSL or termination global state initialized behind the caller's back.
- Listener
CreateThreadfailure cannot leak the listener object or leave the subsystem in a partially running state. - Later
StartSocketsandStopSocketscalls behave deterministically after a failed startup. - Existing successful WebServer/WebSocket startup behavior remains unchanged.
- The item has commit evidence and targeted validation in this file before Beta 0.7.3.
Validation¶
- 2026-05-08: Done in app commit
a4c4dc3. python -m emule_workspace validate --workspace-root .passed.python -m emule_workspace build app --workspace-root . --config Debug --platform x64 --variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-105659.python -m emule_workspace build app --workspace-root . --config Release --platform x64 --variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-105714.- Code validation:
StartSocketsnow wraps listener allocation/start in cleanup that unwinds the termination event, SSL state, and listener object on allocation, exception, orCreateThreadfailure while preserving the normalStopSocketspath after the listener object reaches global state.