From fa20d00d14e4531e36225026100961c714a2bf49 Mon Sep 17 00:00:00 2001 From: Fusion Date: Sun, 24 May 2026 16:13:44 +0200 Subject: [PATCH] debug: add loop exit logging to terminal WebSocket handler --- apps/api/src/api/terminal.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/api/src/api/terminal.py b/apps/api/src/api/terminal.py index c43ed91..1903ff0 100644 --- a/apps/api/src/api/terminal.py +++ b/apps/api/src/api/terminal.py @@ -97,6 +97,11 @@ async def terminal_websocket( return_when=asyncio.FIRST_COMPLETED, ) + # Log which task completed + for task in done: + task_name = "read" if task == read_task else "write" if task == write_task else "heartbeat" + logger.info(f"Task '{task_name}' completed first for instance {instance_id}") + # Cancel remaining tasks for task in pending: task.cancel() @@ -116,24 +121,35 @@ async def terminal_websocket( async def _read_loop(session, websocket) -> None: """Read output from the container and send to WebSocket.""" + loop_count = 0 try: while session.is_alive() and not session._closed: + loop_count += 1 + if loop_count == 1: + logger.info(f"Read loop started for session {session.session_id}, alive={session.is_alive()}, closed={session._closed}") data = await session.read_output() if data: try: await websocket.send_bytes(data) - except Exception: + except Exception as e: + logger.warning(f"Read loop send_bytes failed: {e}") break else: await asyncio.sleep(0.01) - except Exception: - pass + except Exception as e: + logger.warning(f"Read loop exception: {e}") + finally: + logger.info(f"Read loop exited after {loop_count} iterations, alive={session.is_alive()}, closed={session._closed}") async def _write_loop(session, websocket) -> None: """Read input from WebSocket and send to container.""" + loop_count = 0 try: while session.is_alive() and not session._closed: + loop_count += 1 + if loop_count == 1: + logger.info(f"Write loop started for session {session.session_id}, alive={session.is_alive()}, closed={session._closed}") message = await websocket.receive() if message["type"] == "websocket.receive": if "bytes" in message: @@ -177,9 +193,12 @@ async def _write_loop(session, websocket) -> None: else: await session.write_input(text.encode("utf-8")) elif message["type"] == "websocket.disconnect": + logger.info(f"Write loop: websocket.disconnect received for session {session.session_id}") break - except Exception: - pass + except Exception as e: + logger.warning(f"Write loop exception for session {session.session_id}: {e}") + finally: + logger.info(f"Write loop exited after {loop_count} iterations, alive={session.is_alive()}, closed={session._closed}") async def _heartbeat_loop(websocket: WebSocket) -> None: