ssh kitten: Make discarding of garbage data after ssh fails more robust

We now roundtrip an UUID via the terminal and only exit after receiving
it back. This guarantees that any pending data in the pipe is discarded.
This commit is contained in:
Kovid Goyal 2022-07-20 13:28:51 +05:30
parent 79dec269e1
commit bd9e1f58fe
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -27,7 +27,6 @@ from typing import (
Tuple, Union, cast Tuple, Union, cast
) )
from kittens.tui.operations import restore_colors, save_colors
from kitty.constants import ( from kitty.constants import (
cache_dir, runtime_dir, shell_integration_dir, ssh_control_master_template, cache_dir, runtime_dir, shell_integration_dir, ssh_control_master_template,
str_version, terminfo_dir str_version, terminfo_dir
@ -40,6 +39,7 @@ from kitty.utils import (
set_echo as turn_off_echo set_echo as turn_off_echo
) )
from ..tui.operations import restore_colors, save_colors
from ..tui.utils import kitty_opts, running_in_tmux from ..tui.utils import kitty_opts, running_in_tmux
from .config import init_config from .config import init_config
from .copy import CopyInstruction from .copy import CopyInstruction
@ -580,7 +580,6 @@ def ssh_version() -> Tuple[int, int]:
@contextmanager @contextmanager
def drain_potential_tty_garbage(p: 'subprocess.Popen[bytes]', data_request: str) -> Iterator[None]: def drain_potential_tty_garbage(p: 'subprocess.Popen[bytes]', data_request: str) -> Iterator[None]:
ssh_started_at = time.monotonic()
with open(os.open(os.ctermid(), os.O_CLOEXEC | os.O_RDWR | os.O_NOCTTY), 'wb') as tty: with open(os.open(os.ctermid(), os.O_CLOEXEC | os.O_RDWR | os.O_NOCTTY), 'wb') as tty:
if data_request: if data_request:
turn_off_echo(tty.fileno()) turn_off_echo(tty.fileno())
@ -589,14 +588,17 @@ def drain_potential_tty_garbage(p: 'subprocess.Popen[bytes]', data_request: str)
try: try:
yield yield
finally: finally:
if p.returncode and time.monotonic() - ssh_started_at < 30:
# discard queued input data on tty in case data transmission was # discard queued input data on tty in case data transmission was
# interrupted due to SSH failure, avoids spewing garbage to # interrupted due to SSH failure, avoids spewing garbage to screen
# screen from uuid import uuid4
canary = uuid4().hex.encode('ascii')
turn_off_echo(tty.fileno())
tty.write(dcs_to_kitty(canary + b'\n\r', type='echo'))
tty.flush()
data = b'' data = b''
give_up_at = time.monotonic() + 1 give_up_at = time.monotonic() + 2
tty_fd = tty.fileno() tty_fd = tty.fileno()
while time.monotonic() < give_up_at and b'KITTY_DATA_END' not in data: while time.monotonic() < give_up_at and canary not in data:
rd, wr, err = select([tty_fd], [], [tty_fd], max(0, give_up_at - time.monotonic())) rd, wr, err = select([tty_fd], [], [tty_fd], max(0, give_up_at - time.monotonic()))
if err or not rd: if err or not rd:
break break