From 5d83d5f153c8bbce8a238fbc7fcb43277b323dac Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 6 Aug 2022 12:24:50 +0200 Subject: [PATCH] ctrl-c must not kill the ssh subprocess, fixes #6912 --- src/borg/helpers/process.py | 13 +++++++++++++ src/borg/remote.py | 6 ++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/borg/helpers/process.py b/src/borg/helpers/process.py index 0cedcb7b7..e58b919b6 100644 --- a/src/borg/helpers/process.py +++ b/src/borg/helpers/process.py @@ -228,6 +228,19 @@ class SigIntManager: sig_int = SigIntManager() +def ignore_sigint(): + """ + Ignore SIGINT, see also issue #6912. + + Ctrl-C will send a SIGINT to both the main process (borg) and subprocesses + (e.g. ssh for remote ssh:// repos), but often we do not want the subprocess + getting killed (e.g. because it is still needed to cleanly shut down borg). + + To avoid that: Popen(..., preexec_fn=ignore_sigint) + """ + signal.signal(signal.SIGINT, signal.SIG_IGN) + + def popen_with_error_handling(cmd_line: str, log_prefix='', **kwargs): """ Handle typical errors raised by subprocess.Popen. Return None if an error occurred, diff --git a/src/borg/remote.py b/src/borg/remote.py index fa0772c60..637f4d111 100644 --- a/src/borg/remote.py +++ b/src/borg/remote.py @@ -26,7 +26,7 @@ from .helpers import replace_placeholders from .helpers import sysinfo from .helpers import format_file_size from .helpers import safe_unlink -from .helpers import prepare_subprocess_env +from .helpers import prepare_subprocess_env, ignore_sigint from .logger import create_logger, setup_logging from .helpers import msgpack from .repository import Repository @@ -557,7 +557,9 @@ class RemoteRepository: if not testing: borg_cmd = self.ssh_cmd(location) + borg_cmd logger.debug('SSH command line: %s', borg_cmd) - self.p = Popen(borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + # we do not want the ssh getting killed by Ctrl-C/SIGINT because it is needed for clean shutdown of borg. + # borg's SIGINT handler tries to write a checkpoint and requires the remote repo connection. + self.p = Popen(borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env, preexec_fn=ignore_sigint) self.stdin_fd = self.p.stdin.fileno() self.stdout_fd = self.p.stdout.fileno() self.stderr_fd = self.p.stderr.fileno()