1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2025-03-04 10:39:50 +00:00

Merge pull request #6944 from ThomasWaldmann/fix-ctrl-c-remote-repo-1.2

ctrl-c must not kill important subprocesses, fixes #6912
This commit is contained in:
TW 2022-08-13 23:23:50 +02:00 committed by GitHub
commit ec389edc83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 7 deletions

View file

@ -73,7 +73,7 @@ try:
from .helpers import umount
from .helpers import flags_root, flags_dir, flags_special_follow, flags_special
from .helpers import msgpack
from .helpers import sig_int
from .helpers import sig_int, ignore_sigint
from .helpers import iter_separated
from .helpers import get_tar_filter
from .nanorst import rst_to_terminal
@ -527,7 +527,7 @@ class Archiver:
if not dry_run:
try:
try:
proc = subprocess.Popen(args.paths, stdout=subprocess.PIPE)
proc = subprocess.Popen(args.paths, stdout=subprocess.PIPE, preexec_fn=ignore_sigint)
except (FileNotFoundError, PermissionError) as e:
self.print_error('Failed to execute command: %s', e)
return self.exit_code
@ -546,7 +546,7 @@ class Archiver:
paths_sep = eval_escapes(args.paths_delimiter) if args.paths_delimiter is not None else '\n'
if args.paths_from_command:
try:
proc = subprocess.Popen(args.paths, stdout=subprocess.PIPE)
proc = subprocess.Popen(args.paths, stdout=subprocess.PIPE, preexec_fn=ignore_sigint)
except (FileNotFoundError, PermissionError) as e:
self.print_error('Failed to execute command: %s', e)
return self.exit_code

View file

@ -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,
@ -315,10 +328,10 @@ def create_filter_process(cmd, stream, stream_close, inbound=True):
# for us to do something while we block on the process for something different.
if inbound:
proc = popen_with_error_handling(cmd, stdout=subprocess.PIPE, stdin=filter_stream,
log_prefix='filter-process: ', env=env)
log_prefix='filter-process: ', env=env, preexec_fn=ignore_sigint)
else:
proc = popen_with_error_handling(cmd, stdin=subprocess.PIPE, stdout=filter_stream,
log_prefix='filter-process: ', env=env)
log_prefix='filter-process: ', env=env, preexec_fn=ignore_sigint)
if not proc:
raise Error(f'filter {cmd}: process creation failed')
stream = proc.stdout if inbound else proc.stdin

View file

@ -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()