You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by ro...@apache.org on 2020/12/29 13:41:34 UTC

[buildstream] 02/10: utils.py: Don't block on the call's `communicate` call

This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch bschubert/remove-parent-child-pipe
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 30f8f2d77daacfd81aa0e82502dbb1e268761fb5
Author: Benjamin Schubert <co...@benschubert.me>
AuthorDate: Sat Aug 29 09:36:16 2020 +0000

    utils.py: Don't block on the call's `communicate` call
    
    This ensures that, if we were to receive signals or other things while
    we are on this blocking call, we would be able to process them instead
    of waiting for the end of the process
---
 src/buildstream/utils.py | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/buildstream/utils.py b/src/buildstream/utils.py
index 438543b..e9f06aa 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
@@ -1402,7 +1403,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)