From 5856cf2e79ec6cbdd42b037d181b7f70c6cdd515 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Thu, 23 Jul 2020 03:26:25 +0300 Subject: [PATCH] daemon: don't use Popen on linux/mac We used `Popen` just to provide a general way of launching our daemons on both Windows and *nix, but it is causing us issues when dvc is launched from some exotic places (like nix package) or through `main()` helper from a script that is not dvc. This patch makes us just use `main()` directly in our double-forked process. Windows implementation has to use the `Popen` mechanism, because this is the only way to daemonize a process on Windows. This means that dvc on Windows is still susceptible to this problem, but there is nothing we can do about it right now :( Fixes #4206 Fixes #4165 --- dvc/daemon.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/dvc/daemon.py b/dvc/daemon.py index 7dae903ff4..666f0b4132 100644 --- a/dvc/daemon.py +++ b/dvc/daemon.py @@ -18,13 +18,17 @@ def _spawn_windows(cmd, env): from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW + prefix = [sys.executable] + if not is_binary(): + prefix += [sys.argv[0]] + creationflags = CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS startupinfo = STARTUPINFO() startupinfo.dwFlags |= STARTF_USESHOWWINDOW Popen( - cmd, + prefix + cmd, env=env, close_fds=True, shell=False, @@ -34,6 +38,8 @@ def _spawn_windows(cmd, env): def _spawn_posix(cmd, env): + from dvc.main import main + # NOTE: using os._exit instead of sys.exit, because dvc built # with PyInstaller has trouble with SystemExit exception and throws # errors such as "[26338] Failed to execute script __main__" @@ -59,7 +65,8 @@ def _spawn_posix(cmd, env): sys.stdout.close() sys.stderr.close() - Popen(cmd, env=env, close_fds=True, shell=False).communicate() + os.environ.update(env) + main(cmd) os._exit(0) # pylint: disable=protected-access @@ -87,10 +94,7 @@ def daemon(args): logger.debug("skipping launching a new daemon.") return - cmd = [sys.executable] - if not is_binary(): - cmd += [sys.argv[0]] - cmd += ["daemon", "-q"] + args + cmd = ["daemon", "-q"] + args env = fix_env() file_path = os.path.abspath(inspect.stack()[0][1])