From a66e6b603fbf675e072ba343a225bfebf50cc76f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 25 Nov 2016 15:45:43 +0100 Subject: [PATCH] Make sure our command line calls always exit sarge's "wait_events" is unreliable. If an asynchronous job is started but stops immediately and raises a sarge Exception (inside the async thread), the associated command's event will never be set event though the process finished. So we'd wait indefinitely here. We circumvent this by first waiting until the commands are parsed and processed (p.commands contains elements), then until said commands are started and then making sure the command's process is actually set. Only then do we actually have a background process running that we'll be able to monitor further down, otherwise the command immediately failed. --- src/octoprint/util/commandline.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/octoprint/util/commandline.py b/src/octoprint/util/commandline.py index 47b8f424..97678d60 100644 --- a/src/octoprint/util/commandline.py +++ b/src/octoprint/util/commandline.py @@ -9,6 +9,7 @@ __copyright__ = "Copyright (C) 2015 The OctoPrint Project - Released under terms import sarge import logging import re +import time from . import to_unicode @@ -80,7 +81,21 @@ class CommandlineCaller(object): kwargs.update(dict(async=True, stdout=sarge.Capture(), stderr=sarge.Capture())) p = sarge.run(command, **kwargs) - p.wait_events() + while len(p.commands) == 0: + # somewhat ugly... we can't use wait_events because + # the events might not be all set if an exception + # by sarge is triggered within the async process + # thread + time.sleep(0.01) + + # by now we should have a command, let's wait for its + # process to have been prepared + p.commands[0].process_ready.wait() + + if not p.commands[0].process: + # the process might have been set to None in case of any exception + self._logger.error(u"Error while trying to run command {}".format(joined_command)) + return None, [], [] all_stdout = [] all_stderr = []