diff --git a/kitty/boss.py b/kitty/boss.py index 6b708d2e1..9ce4e3641 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -16,9 +16,7 @@ from typing import ( ) from weakref import WeakValueDictionary -from .child import ( - cached_process_data, default_env, set_default_env -) +from .child import cached_process_data, default_env, set_default_env from .cli import create_opts, parse_args from .cli_stub import CLIOptions from .conf.utils import BadLine, KeyAction, to_cmdline @@ -58,10 +56,11 @@ from .tabs import ( from .types import _T, AsyncResponse, SingleKey, WindowSystemMouseEvent, ac from .typing import PopenType, TypedDict from .utils import ( - func_name, get_editor, get_new_os_window_size, get_primary_selection, - is_path_in_temp_dir, log_error, open_url, parse_address_spec, - parse_uri_list, platform_window_id, remove_socket_file, safe_print, - set_primary_selection, single_instance, startup_notification_handler, which + cleanup_ssh_control_masters, func_name, get_editor, get_new_os_window_size, + get_primary_selection, is_path_in_temp_dir, log_error, open_url, + parse_address_spec, parse_uri_list, platform_window_id, remove_socket_file, + safe_print, set_primary_selection, single_instance, + startup_notification_handler, which ) from .window import CommandOutput, MatchPatternType, Window @@ -2263,6 +2262,10 @@ class Boss: output = '\n'.join(f'{k}={v}' for k, v in os.environ.items()) self.display_scrollback(w, output, title=_('Current kitty env vars'), report_cursor=False) + @ac('debug', 'Close all shared SSH connections') + def close_shared_ssh_connections(self) -> None: + cleanup_ssh_control_masters() + def launch_urls(self, *urls: str, no_replace_window: bool = False) -> None: from .launch import force_window_launch from .open_actions import actions_for_launch diff --git a/kitty/main.py b/kitty/main.py index 4fbf97077..6b016da77 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -17,8 +17,7 @@ from .conf.utils import BadLine from .config import cached_values_for from .constants import ( appname, beam_cursor_data_file, config_dir, glfw_path, is_macos, - is_wayland, kitty_exe, logo_png_file, running_in_kitty, runtime_dir, - ssh_control_master_template + is_wayland, kitty_exe, logo_png_file, running_in_kitty ) from .fast_data_types import ( GLFW_IBEAM_CURSOR, GLFW_MOD_ALT, GLFW_MOD_SHIFT, create_os_window, @@ -33,8 +32,8 @@ from .os_window_size import initial_window_size_func from .session import get_os_window_sizing_data from .types import SingleKey from .utils import ( - detach, expandvars, log_error, single_instance, - startup_notification_handler, unix_socket_paths + cleanup_ssh_control_masters, detach, expandvars, log_error, + single_instance, startup_notification_handler, unix_socket_paths ) from .window import load_shader_programs @@ -346,24 +345,6 @@ def set_locale() -> None: log_error('Failed to set locale with no LANG') -def cleanup_ssh_control_masters() -> None: - import glob - import subprocess - try: - files = frozenset(glob.glob(os.path.join(runtime_dir(), ssh_control_master_template.format( - kitty_pid=os.getpid(), ssh_placeholder='*')))) - except OSError: - return - workers = tuple(subprocess.Popen([ - 'ssh', '-o', f'ControlPath={x}', '-O', 'exit', 'kitty-unused-host-name'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - for x in files) - for w in workers: - w.wait() - for x in files: - with suppress(OSError): - os.remove(x) - - def _main() -> None: running_in_kitty(True) with suppress(AttributeError): # python compiled without threading diff --git a/kitty/utils.py b/kitty/utils.py index 0e7d5bab9..5eebbd924 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -18,7 +18,8 @@ from typing import ( ) from .constants import ( - appname, config_dir, is_macos, is_wayland, read_kitty_resource, shell_path, + appname, config_dir, is_macos, is_wayland, read_kitty_resource, + runtime_dir, shell_path, ssh_control_master_template, supports_primary_selection ) from .fast_data_types import Color, open_tty @@ -917,3 +918,21 @@ def hold_till_enter() -> None: break if q in b'\x03\x04': write_all(fd, msg) + + +def cleanup_ssh_control_masters() -> None: + import glob + import subprocess + try: + files = frozenset(glob.glob(os.path.join(runtime_dir(), ssh_control_master_template.format( + kitty_pid=os.getpid(), ssh_placeholder='*')))) + except OSError: + return + workers = tuple(subprocess.Popen([ + 'ssh', '-o', f'ControlPath={x}', '-O', 'exit', 'kitty-unused-host-name'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + for x in files) + for w in workers: + w.wait() + for x in files: + with suppress(OSError): + os.remove(x)