Problem (ARIA journal 2026-09-11/23): the listening socket was SSL-wrapped, so serve_forever's accept() ran the TLS handshake inline. A client that completed TCP but vanished mid-handshake (phone losing network/VPN) blocked do_handshake() forever — no new device connections accepted (app couldn't reconnect); on restart stop()→httpd.shutdown() froze the event loop until the watchdog killed it.
Fix: (1) TLS handshake moved to the per-connection thread under a hard timeout (HANDSHAKE_TIMEOUT_S=10s); failed/timed-out handshakes just close the socket. (2) stop() runs shutdown()/server_close()/join in an executor under asyncio.wait_for(10s) — teardown can no longer freeze the event loop.
Test: new regression test (half-open silent TCP conn: fresh TLS /v1/health still 200, stop() bounded). Fails on old code, passes on fixed. 134/134 green, ruff clean.
**Problem** (ARIA journal 2026-09-11/23): the listening socket was SSL-wrapped, so `serve_forever`'s `accept()` ran the TLS handshake inline. A client that completed TCP but vanished mid-handshake (phone losing network/VPN) blocked `do_handshake()` forever — no new device connections accepted (app couldn't reconnect); on restart `stop()`→`httpd.shutdown()` froze the event loop until the watchdog killed it.
**Fix**: (1) TLS handshake moved to the per-connection thread under a hard timeout (`HANDSHAKE_TIMEOUT_S=10s`); failed/timed-out handshakes just close the socket. (2) `stop()` runs `shutdown()`/`server_close()`/join in an executor under `asyncio.wait_for(10s)` — teardown can no longer freeze the event loop.
**Test**: new regression test (half-open silent TCP conn: fresh TLS `/v1/health` still 200, `stop()` bounded). Fails on old code, passes on fixed. 134/134 green, ruff clean.
**Deploy**: update `/home/aria/.hermes/profiles/aria/plugins/iris-platform/` + restart.
A client that completes TCP but vanishes mid-TLS-handshake (e.g. a
phone losing its network/VPN while traveling) blocked
ssl.SSLSocket.accept() inside serve_forever forever: the gateway
stopped accepting any new device connections (the app could not
reconnect), and on the next restart httpd.shutdown() froze the whole
event loop until the shutdown watchdog killed the process (ARIA
journal 2026-09-11 / 2026-09-23).
- Move the TLS handshake out of the accept loop: it now runs in the
per-connection thread under a hard timeout (HANDSHAKE_TIMEOUT_S,
10 s); a failed/timed-out handshake just closes the socket.
- stop() no longer blocks the event loop: shutdown()/server_close()/
join run in an executor under asyncio.wait_for(10 s); if the bound
expires the daemon threads are abandoned.
- Regression test: a silent half-open TCP connection must not stop
fresh TLS connections from being served, and stop() must stay
bounded.
✅ No issues found — changes look consistent with the stated intent. Ready to be merged.
The implementation is clean and correct:
TLS moved to per-connection thread: process_request correctly spawns a thread that performs wrap_socket (handshake) under a hard timeout before delegating to the parent's process_request. The OSError catch covers both ssl.SSLError and socket.timeout/TimeoutError.
Bounded teardown: stop() runs shutdown()/server_close()/join in an executor with asyncio.wait_for(10s), and the except Exception correctly catches asyncio.TimeoutError (which is a subclass of Exception across all supported Python versions).
Test: The half-open TCP connection + fresh TLS health check + bounded stop() assertion directly validates the regression scenario. The monkeypatch of HANDSHAKE_TIMEOUT_S to 0.5s keeps the test fast.
✅ No issues found — changes look consistent with the stated intent. Ready to be merged.
The implementation is clean and correct:
- **TLS moved to per-connection thread**: `process_request` correctly spawns a thread that performs `wrap_socket` (handshake) under a hard timeout before delegating to the parent's `process_request`. The `OSError` catch covers both `ssl.SSLError` and `socket.timeout`/`TimeoutError`.
- **Bounded teardown**: `stop()` runs `shutdown()`/`server_close()`/`join` in an executor with `asyncio.wait_for(10s)`, and the `except Exception` correctly catches `asyncio.TimeoutError` (which is a subclass of `Exception` across all supported Python versions).
- **Test**: The half-open TCP connection + fresh TLS health check + bounded `stop()` assertion directly validates the regression scenario. The `monkeypatch` of `HANDSHAKE_TIMEOUT_S` to `0.5s` keeps the test fast.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem (ARIA journal 2026-09-11/23): the listening socket was SSL-wrapped, so
serve_forever'saccept()ran the TLS handshake inline. A client that completed TCP but vanished mid-handshake (phone losing network/VPN) blockeddo_handshake()forever — no new device connections accepted (app couldn't reconnect); on restartstop()→httpd.shutdown()froze the event loop until the watchdog killed it.Fix: (1) TLS handshake moved to the per-connection thread under a hard timeout (
HANDSHAKE_TIMEOUT_S=10s); failed/timed-out handshakes just close the socket. (2)stop()runsshutdown()/server_close()/join in an executor underasyncio.wait_for(10s)— teardown can no longer freeze the event loop.Test: new regression test (half-open silent TCP conn: fresh TLS
/v1/healthstill 200,stop()bounded). Fails on old code, passes on fixed. 134/134 green, ruff clean.Deploy: update
/home/aria/.hermes/profiles/aria/plugins/iris-platform/+ restart.✅ No issues found — changes look consistent with the stated intent. Ready to be merged.
The implementation is clean and correct:
process_requestcorrectly spawns a thread that performswrap_socket(handshake) under a hard timeout before delegating to the parent'sprocess_request. TheOSErrorcatch covers bothssl.SSLErrorandsocket.timeout/TimeoutError.stop()runsshutdown()/server_close()/joinin an executor withasyncio.wait_for(10s), and theexcept Exceptioncorrectly catchesasyncio.TimeoutError(which is a subclass ofExceptionacross all supported Python versions).stop()assertion directly validates the regression scenario. ThemonkeypatchofHANDSHAKE_TIMEOUT_Sto0.5skeeps the test fast.