HTTPS WebSocket queued writes can stall after TLS WANT_READ
Summary¶
The HTTPS WebSocket send path treats MBEDTLS_ERR_SSL_WANT_READ and
MBEDTLS_ERR_SSL_WANT_WRITE as the same condition, queues unsent data, and only
drains queued data from the FD_WRITE branch. If mbedTLS needs read-side
progress to finish a write, queued response data can remain stuck indefinitely.
This blocks Beta 0.7.3 because a slow or adversarial HTTPS Web UI client can wedge a request thread and interact badly with shutdown.
Evidence¶
srchybrid/WebSocket.cpp:51maps both TLS WANT results throughIsTlsWant.srchybrid/WebSocket.cpp:310attempts direct HTTPS writes and queues remaining bytes whenIsTlsWantis returned.srchybrid/WebSocket.cpp:473handlesFD_READby reading only; it does not retry queued writes when the previous write wanted read-side progress.srchybrid/WebSocket.cpp:497drains queued sends only underFD_WRITE.srchybrid/WebSocket.cpp:550keeps the accepted thread alive whilem_pHeadremains queued.
Execution Plan¶
- Split TLS WANT handling so the connection remembers whether the pending TLS operation needs read readiness, write readiness, or either.
- Ensure queued writes are retried after the readiness condition requested by
mbedTLS, including
WANT_READ. - Avoid busy loops by returning to
WSAEventSelect/wait readiness between retries. - Preserve legacy plain HTTP send behavior.
- Add a seam-level test for a TLS write returning
WANT_READwith queued response data. - Add a shutdown regression where a queued HTTPS response does not keep the WebSocket subsystem alive indefinitely.
Acceptance Criteria¶
- Queued HTTPS sends drain after both TLS
WANT_READandWANT_WRITEpaths. - The fix does not introduce a CPU spin under repeated TLS WANT responses.
- Shutdown can drain or abandon a queued HTTPS response without leaking threads or handles.
- Existing REST malformed/concurrent request coverage remains green.
Validation¶
- 2026-05-08: Done in app commit
dfcf1fe. python -m emule_workspace validate --workspace-root .passed.python -m emule_workspace build app --workspace-root . --config Release --platform x64 --variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-094234.- Code validation: queued WebSocket sends now drain through one helper, and the
HTTPS accepted-client loop retries queued writes after read readiness so a
previous TLS
WANT_READcannot wait forever forFD_WRITE.