summaryrefslogtreecommitdiff
path: root/src/buildstream/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildstream/utils.py')
-rw-r--r--src/buildstream/utils.py16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/buildstream/utils.py b/src/buildstream/utils.py
index 94ff931ad..1d1336cb4 100644
--- a/src/buildstream/utils.py
+++ b/src/buildstream/utils.py
@@ -32,6 +32,7 @@ import signal
import stat
from stat import S_ISDIR
import subprocess
+from subprocess import TimeoutExpired
import tempfile
import time
import datetime
@@ -1397,7 +1398,20 @@ def _call(*popenargs, terminate=False, **kwargs):
process = subprocess.Popen( # pylint: disable=subprocess-popen-preexec-fn
*popenargs, preexec_fn=preexec_fn, universal_newlines=True, **kwargs
)
- output, _ = process.communicate()
+ # Here, we don't use `process.communicate()` directly without a timeout
+ # This is because, if we were to do that, and the process would never
+ # output anything, the control would never be given back to the python
+ # process, which might thus not be able to check for request to
+ # shutdown, or kill the process.
+ # We therefore loop with a timeout, to ensure the python process
+ # can act if it needs.
+ while True:
+ try:
+ output, _ = process.communicate(timeout=1)
+ break
+ except TimeoutExpired:
+ continue
+
exit_code = process.poll()
return (exit_code, output)