fix: WebSSH terminal echo delay — replace readline() with read()
asyncssh's async-for on shell.stdout internally calls readline() which buffers until a newline is found. For interactive terminal use, single-character echo never contains a newline, so all typed characters were buffered until Enter was pressed. Fix: use shell.stdout.read(4096) which returns data as soon as any is available, and set bufsize=4096 on create_process() to reduce the internal read buffer from 128KB to 4KB for low-latency interactive echo. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+16
-6
@@ -180,6 +180,7 @@ async def terminal_ws(
|
||||
shell_proc = conn.create_process(
|
||||
term_type="xterm-256color",
|
||||
term_size=(24, 80),
|
||||
bufsize=4096, # Small buffer for low-latency interactive echo
|
||||
)
|
||||
except Exception as e:
|
||||
# Stale pooled connection — force-close and retry with fresh connection
|
||||
@@ -190,6 +191,7 @@ async def terminal_ws(
|
||||
shell_proc = conn.create_process(
|
||||
term_type="xterm-256color",
|
||||
term_size=(24, 80),
|
||||
bufsize=4096, # Small buffer for low-latency interactive echo
|
||||
)
|
||||
except Exception as e2:
|
||||
logger.error(f"WebSSH shell creation failed on fresh connection (server={server.id}): {type(e2).__name__}: {e2!r}")
|
||||
@@ -218,13 +220,21 @@ async def terminal_ws(
|
||||
command_buffer = "" # Buffer for command logging
|
||||
|
||||
async def _read_shell_output():
|
||||
"""Read SSH shell output -> send to WebSocket client"""
|
||||
"""Read SSH shell output -> send to WebSocket client
|
||||
|
||||
Uses read() instead of async-for to avoid readline() buffering.
|
||||
async-for calls readline() internally, which waits for newline
|
||||
characters before yielding — causing echo delay in interactive
|
||||
terminal use. read(n) returns data as soon as any is available.
|
||||
"""
|
||||
try:
|
||||
async for data in shell.stdout:
|
||||
await websocket.send_json({
|
||||
"type": MSG_DATA,
|
||||
"data": data,
|
||||
})
|
||||
while not shell.stdout.at_eof():
|
||||
data = await shell.stdout.read(4096)
|
||||
if data:
|
||||
await websocket.send_json({
|
||||
"type": MSG_DATA,
|
||||
"data": data,
|
||||
})
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user