Skip to content

WebSocket timeout shutdown leaves global state unsafe for restart

Summary

The current cooperative WebSocket shutdown avoids closing the termination handle while threads are still alive, but timeout paths leave global listener, accepted thread, termination-handle, and SSL state resident. A later start on a release build can overwrite or reuse global state after only debug ASSERT coverage.

This blocks Beta 0.7.3 until the timeout/restart semantics are explicit and safe.

Evidence

  • srchybrid/WebSocket.cpp:764 waits for the listener for a fixed timeout.
  • srchybrid/WebSocket.cpp:775 deletes and clears s_pSocketThread only when the wait path is considered safe.
  • srchybrid/WebSocket.cpp:781 waits for accepted-client handles, but timeout keeps the termination handle open.
  • srchybrid/WebSocket.cpp:784 closes s_hTerminate and calls StopSSL only when all waits succeed.
  • srchybrid/WebSocket.cpp:788 logs that the termination handle is kept open, but there is no release-mode restart guard or terminal state.

Execution Plan

  1. Define the WebSocket subsystem states for stopped, running, stopping, and failed-stopping.
  2. Make StartSockets fail closed if a previous shutdown left threads or shared state alive.
  3. Ensure timeout paths either complete cleanup safely or mark the subsystem as non-restartable until process exit.
  4. Avoid overwriting live global handles or SSL state in release builds.
  5. Add diagnostics that identify which thread class prevented shutdown.
  6. Add targeted coverage or a seam that simulates listener and accepted-client wait timeouts.

Acceptance Criteria

  • A failed WebSocket shutdown cannot overwrite s_hTerminate, s_pSocketThread, accepted-thread state, or SSL globals on restart.
  • The user-visible result of a failed restart is deterministic and logged.
  • Successful shutdown/start cycles still work for HTTP and HTTPS.
  • No forced thread termination is reintroduced.

Validation

  • 2026-05-08: Done in app commit 7a5de38.
  • python -m emule_workspace build app --workspace-root . --config Release --platform x64 --variant main passed; log root workspaces\v0.72a\state\build-logs\20260508-094503.
  • python -m emule_workspace validate --workspace-root . passed.
  • Code validation: StartSockets now attempts to reap deferred shutdown state before startup and fails closed in release builds if listener, accepted-client, or termination-handle state is still active.