From 55702777bb0ea942d40ae3e41ebcd94aa51c293e Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 23 Sep 2017 19:04:46 +0200 Subject: [PATCH] refactor/fix subprocess env preparation refactor: make a generally usable function fix: remove support code for ancient pyinstaller the "else" branch was needed for pyinstaller < 20160820 because it did not have the LD_LIBRARY_PATH_ORIG env var, so we just killed LDLP because we had no better way. but with borg tests running under fakeroot, this is troublesome as fakeroot uses this also and can't find its library without it. so, just remove it, we do not need to support old pyinstaller. (cherry picked from commit 5dd16672c0e82e1bde24c53a45629527bda77d2a) --- borg/helpers.py | 26 ++++++++++++++++++++++++++ borg/remote.py | 10 ++++------ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/borg/helpers.py b/borg/helpers.py index 6d193bbff..2f828f9c8 100644 --- a/borg/helpers.py +++ b/borg/helpers.py @@ -1563,3 +1563,29 @@ def raising_signal_handler(exc_cls): raise exc_cls return handler + + +def prepare_subprocess_env(system, env=None): + """ + Prepare the environment for a subprocess we are going to create. + + :param system: True for preparing to invoke system-installed binaries, + False for stuff inside the pyinstaller environment (like borg, python). + :param env: optionally give a environment dict here. if not given, default to os.environ. + :return: a modified copy of the environment + """ + env = dict(env if env is not None else os.environ) + if system: + # a pyinstaller binary's bootloader modifies LD_LIBRARY_PATH=/tmp/_ME..., + # but we do not want that system binaries (like ssh or other) pick up + # (non-matching) libraries from there. + # thus we install the original LDLP, before pyinstaller has modified it: + lp_key = 'LD_LIBRARY_PATH' + lp_orig = env.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this + if lp_orig is not None: + env[lp_key] = lp_orig + # security: do not give secrets to subprocess + env.pop('BORG_PASSPHRASE', None) + # for information, give borg version to the subprocess + env['BORG_VERSION'] = borg_version + return env diff --git a/borg/remote.py b/borg/remote.py index 45bdb4fd1..6408d9c5d 100644 --- a/borg/remote.py +++ b/borg/remote.py @@ -16,6 +16,7 @@ from .helpers import Error, IntegrityError, sysinfo from .helpers import replace_placeholders from .helpers import BUFSIZE from .helpers import get_limited_unpacker +from .helpers import prepare_subprocess_env from .repository import Repository from .logger import create_logger @@ -209,15 +210,12 @@ class RemoteRepository: self.unpacker = get_limited_unpacker('client') self.p = None testing = location.host == '__testsuite__' + # when testing, we invoke and talk to a borg process directly (no ssh). + # when not testing, we invoke the system-installed ssh binary to talk to a remote borg. + env = prepare_subprocess_env(system=not testing) borg_cmd = self.borg_cmd(args, testing) - env = dict(os.environ) if not testing: borg_cmd = self.ssh_cmd(location) + borg_cmd - # pyinstaller binary adds LD_LIBRARY_PATH=/tmp/_ME... but we do not want - # that the system's ssh binary picks up (non-matching) libraries from there - env.pop('LD_LIBRARY_PATH', None) - env.pop('BORG_PASSPHRASE', None) # security: do not give secrets to subprocess - env['BORG_VERSION'] = __version__ logger.debug('SSH command line: %s', borg_cmd) self.p = Popen(borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) self.stdin_fd = self.p.stdin.fileno()