fix: use docker exec -i instead of -it so host PTY resize propagates to container
Removes -t flag from docker exec so it uses our PTY slave directly instead of creating its own PTY inside the container. This allows TIOCSWINSZ on the host PTY master to propagate naturally to the container shell via SIGWINCH. Also removes all stty command injection logic since resize now works natively.
This commit is contained in:
@@ -61,11 +61,15 @@ class TerminalSession:
|
||||
logger.info(f"Starting terminal session {self.session_id} for container {self.container_id} with initial size {self._cols}x{self._rows}")
|
||||
|
||||
# Start docker exec with the slave fd as stdin/stdout/stderr
|
||||
# Using -it because the slave fd IS a TTY
|
||||
# Using -i (interactive) but NOT -t (tty) because:
|
||||
# 1. The slave fd IS a TTY
|
||||
# 2. docker exec -t creates its OWN PTY inside the container
|
||||
# 3. This prevents host PTY resize from propagating to the container shell
|
||||
# By using only -i, docker exec uses our PTY slave directly
|
||||
self.process = await asyncio.create_subprocess_exec(
|
||||
"docker",
|
||||
"exec",
|
||||
"-it",
|
||||
"-i",
|
||||
"-e",
|
||||
"TERM=xterm",
|
||||
self.container_id,
|
||||
@@ -151,17 +155,6 @@ class TerminalSession:
|
||||
self._rows = rows
|
||||
logger.info(f"resize() called for session {self.session_id}: {cols}x{rows}")
|
||||
self._set_terminal_size(cols, rows)
|
||||
|
||||
# Docker exec doesn't forward PTY resize to the container process,
|
||||
# so we need to explicitly set the size inside the container shell.
|
||||
# Send on every resize so the container shell always matches the frontend.
|
||||
# Use stty -echo to prevent the command from being visible, then clear the line.
|
||||
stty_cmd = (
|
||||
f"stty -echo; stty cols {cols} rows {rows}; stty echo\n"
|
||||
f"\x1b[A\x1b[M" # Move up 1 line and delete it (clears the stty command)
|
||||
).encode()
|
||||
await self.write_input(stty_cmd)
|
||||
logger.debug(f"Sent stty resize to container for session {self.session_id}: {cols}x{rows}")
|
||||
|
||||
async def reset(self) -> None:
|
||||
"""Reset the session by killing the process and clearing state."""
|
||||
|
||||
Reference in New Issue
Block a user