From 7c540da5c4bd935e1f4a0540daf1e93447f8cc44 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Sun, 7 Apr 2019 18:10:30 +0300 Subject: [PATCH] daemon: don't spawn recursively Fixes #1803 Signed-off-by: Ruslan Kuprieiev --- dvc/daemon.py | 44 ++++++++++++++++++++++++--------------- dvc/env.py | 1 + tests/unit/test_daemon.py | 8 +++++++ 3 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 dvc/env.py diff --git a/dvc/daemon.py b/dvc/daemon.py index fc0d1e458..34ab50898 100644 --- a/dvc/daemon.py +++ b/dvc/daemon.py @@ -8,6 +8,7 @@ import inspect import logging from subprocess import Popen +from dvc.env import DVC_DAEMON from dvc.utils import is_binary, fix_env from dvc.utils.compat import cast_bytes_py2 @@ -68,23 +69,7 @@ def _spawn_posix(cmd, env): os._exit(0) # pylint: disable=protected-access -def daemon(args): - """Launch a `dvc daemon` command in a detached process. - - Args: - args (list): list of arguments to append to `dvc daemon` command. - """ - cmd = [sys.executable] - if not is_binary(): - cmd += ["-m", "dvc"] - cmd += ["daemon", "-q"] + args - - env = fix_env() - file_path = os.path.abspath(inspect.stack()[0][1]) - env[cast_bytes_py2("PYTHONPATH")] = cast_bytes_py2( - os.path.dirname(os.path.dirname(file_path)) - ) - +def _spawn(cmd, env): logger.debug("Trying to spawn '{}'".format(cmd)) if os.name == "nt": @@ -95,3 +80,28 @@ def daemon(args): raise NotImplementedError logger.debug("Spawned '{}'".format(cmd)) + + +def daemon(args): + """Launch a `dvc daemon` command in a detached process. + + Args: + args (list): list of arguments to append to `dvc daemon` command. + """ + if os.environ.get(DVC_DAEMON): + logger.debug("skipping launching a new daemon.") + return + + cmd = [sys.executable] + if not is_binary(): + cmd += ["-m", "dvc"] + cmd += ["daemon", "-q"] + args + + env = fix_env() + file_path = os.path.abspath(inspect.stack()[0][1]) + env[cast_bytes_py2("PYTHONPATH")] = cast_bytes_py2( + os.path.dirname(os.path.dirname(file_path)) + ) + env[cast_bytes_py2(DVC_DAEMON)] = "1" + + _spawn(cmd, env) diff --git a/dvc/env.py b/dvc/env.py new file mode 100644 index 000000000..be4967912 --- /dev/null +++ b/dvc/env.py @@ -0,0 +1 @@ +DVC_DAEMON = "DVC_DAEMON" diff --git a/tests/unit/test_daemon.py b/tests/unit/test_daemon.py index 43c9de862..d5c4198a2 100644 --- a/tests/unit/test_daemon.py +++ b/tests/unit/test_daemon.py @@ -29,3 +29,11 @@ class TestDaemon(TestCase): test_dir = os.path.dirname(file_dir) dvc_dir = os.path.dirname(test_dir) self.assertEqual(env["PYTHONPATH"], dvc_dir) + self.assertEqual(env[daemon.DVC_DAEMON], "1") + + +def test_no_recursive_spawn(): + with mock.patch.dict(os.environ, {daemon.DVC_DAEMON: "1"}): + with mock.patch("dvc.daemon._spawn") as mock_spawn: + daemon.daemon(["updater"]) + mock_spawn.assert_not_called()