fix: send SIGWINCH to docker exec process for container terminal resize
Instead of sending stty commands through the user's terminal session (which causes 'inappropriate ioctl' errors), send SIGWINCH signal to the docker exec process on the host. Docker exec should forward this to the container process, causing the shell to re-read its terminal size. This avoids: - Visible stty commands in the terminal - ioctl errors from stty - Interference with user's shell session
This commit is contained in:
@@ -5,6 +5,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import pty
|
import pty
|
||||||
import select
|
import select
|
||||||
|
import signal
|
||||||
import struct
|
import struct
|
||||||
import fcntl
|
import fcntl
|
||||||
import time
|
import time
|
||||||
@@ -153,14 +154,18 @@ class TerminalSession:
|
|||||||
self._set_terminal_size(cols, rows)
|
self._set_terminal_size(cols, rows)
|
||||||
|
|
||||||
# Docker exec -it creates its own PTY inside the container,
|
# Docker exec -it creates its own PTY inside the container,
|
||||||
# so host PTY resize doesn't propagate. We must send stty manually.
|
# so host PTY resize doesn't propagate to the container shell.
|
||||||
# To hide the command from the user:
|
# Send SIGWINCH to the docker exec process on the host.
|
||||||
# 1. \r moves cursor to start of current line (overwrites prompt)
|
# Docker exec forwards signals to the container process, which should
|
||||||
# 2. stty command executes silently (no output on success)
|
# cause the container's shell to re-read its terminal size.
|
||||||
# 3. \r moves cursor back to start, hiding the echoed command
|
if self.process and self.process.pid:
|
||||||
stty_cmd = f"\rstty cols {cols} rows {rows}\r".encode()
|
try:
|
||||||
await self.write_input(stty_cmd)
|
os.kill(self.process.pid, signal.SIGWINCH)
|
||||||
logger.debug(f"Sent stty resize to container for session {self.session_id}: {cols}x{rows}")
|
logger.debug(f"Sent SIGWINCH to docker exec process {self.process.pid} for session {self.session_id}")
|
||||||
|
except ProcessLookupError:
|
||||||
|
logger.warning(f"docker exec process {self.process.pid} not found for session {self.session_id}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to send SIGWINCH: {e}")
|
||||||
|
|
||||||
async def reset(self) -> None:
|
async def reset(self) -> None:
|
||||||
"""Reset the session by killing the process and clearing state."""
|
"""Reset the session by killing the process and clearing state."""
|
||||||
|
|||||||
Reference in New Issue
Block a user