From 2c76125128f326d5decfaeaac8e1c8cea34853b5 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Tue, 6 Oct 2026 11:20:52 -0700 Subject: [PATCH] fix(dashboard): a cancelled 1:1 PTY handler still drops its channel marker The marker discard ran after `await _legacy_pump(...)`. When the client goes away, the handler task is cancelled while the pump is still awaiting bridge.close in a worker thread, so the discard never ran and the channel kept a stale marker. It now runs in a finally. test_legacy_channel_connect_pops_marker_on_disconnect hit this on CI: TestClient cancels the app task on context exit. --- hermes_cli/web_routers/chat_ws.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/hermes_cli/web_routers/chat_ws.py b/hermes_cli/web_routers/chat_ws.py index f463430ec3..94bf471939 100644 --- a/hermes_cli/web_routers/chat_ws.py +++ b/hermes_cli/web_routers/chat_ws.py @@ -626,13 +626,17 @@ async def pty_ws(ws: WebSocket) -> None: _discard_active_session_file(ws.app, channel, active_session_file) await _pty_fail(ws, exc) return - await _legacy_pump(ws, bridge) - # The 1:1 PTY died with this socket; nothing survives to keep the - # breadcrumb, so drop the marker instead of leaking the entry (#63553). - # A preexisting marker belongs to a live keep-alive PTY on this channel - # — only the marker this handler allocated is ours to drop. - if not marker_preexisting: - _discard_active_session_file(ws.app, channel, active_session_file) + try: + await _legacy_pump(ws, bridge) + finally: + # The 1:1 PTY died with this socket; nothing survives to keep the + # breadcrumb, so drop the marker instead of leaking the entry (#63553). + # A preexisting marker belongs to a live keep-alive PTY on this channel + # — only the marker this handler allocated is ours to drop. In a + # finally: a handler cancelled mid-teardown (client gone, server + # shutdown) must still drop it. + if not marker_preexisting: + _discard_active_session_file(ws.app, channel, active_session_file) return # Keep-alive path: the PTY outlives this socket; reattach by token.