WebSocket shutdown can forcibly terminate the listener thread
Summary¶
The WebSocket shutdown path still calls TerminateThread if the listener thread
does not exit within 1300 ms. Forced termination in MFC/CRT/networking code can
leave locks, heap state, TLS state, or WinSock state corrupted.
This blocks Beta 0.7.3 because forced thread termination is not compatible with the release goal of absolute shutdown stability.
Evidence¶
srchybrid/WebSocket.cpp:631waits for the listener thread.srchybrid/WebSocket.cpp:634callsTerminateThreadon timeout.srchybrid/WebSocket.cpp:641deletes theCWinThreadobject after that path.
Execution Plan¶
- Revalidate why the listener can outlive the current wait.
- Make listener shutdown cooperative by combining termination signaling with socket/event wakeup.
- Remove the
TerminateThreadfallback. - If the listener still fails to exit, log a release-grade error and keep ownership safe rather than corrupting process state.
- Align this work with BUG-079 so listener and accepted-client ownership use one coherent shutdown model.
Acceptance Criteria¶
- No WebSocket shutdown path calls
TerminateThread. - Listener shutdown is deterministic under normal, idle, and active-client cases.
- Timeout handling cannot corrupt process state.
Validation¶
- 2026-05-08: Done in app commit
aa66699. python -m emule_workspace validate --workspace-root .python -m emule_workspace build app --workspace-root . --config Release --platform x64 --variant main- Code validation:
StopSockets()no longer callsTerminateThread; listener timeout paths log and preserve ownership instead of forcibly killing MFC/CRT code.