summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2017-07-03 20:34:39 +0900
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2017-07-03 20:34:39 +0900
commitede78f49b96825194f41e2264e807c95eea8d88a (patch)
tree3b1294336be202d8e828ca3f2cac758fb67c73d4
parent4f3dcabd9c3abd8c992ca0d824aec45f722c6e06 (diff)
downloadbuildstream-ede78f49b96825194f41e2264e807c95eea8d88a.tar.gz
utils.py: Optional 'terminate' argument to _call() private function.
By default we brutally murder subprocess trees, but sometimes we know the nature of the tool we are using and know that it handles sigterm gracefully. This patch allows those cases to have a chance at graceful termination.
-rw-r--r--buildstream/utils.py48
1 files changed, 32 insertions, 16 deletions
diff --git a/buildstream/utils.py b/buildstream/utils.py
index e9726933b..7a254fbc2 100644
--- a/buildstream/utils.py
+++ b/buildstream/utils.py
@@ -670,34 +670,50 @@ def _kill_process_tree(pid):
#
# Args:
# popenargs (list): Popen() arguments
+# terminate (bool): Whether to attempt graceful termination before killing
# rest_of_args (kwargs): Remaining arguments to subprocess.call()
#
# Returns:
# (int): The process exit code.
# (str): The program output.
#
-def _call(*popenargs, **kwargs):
+def _call(*popenargs, terminate=False, **kwargs):
kwargs['start_new_session'] = True
# Handle termination, suspend and resume
def kill_proc():
if process:
- # FIXME: This is a brutal but reliable approach
- #
- # Other variations I've tried which try SIGTERM first
- # and then wait for child processes to exit gracefully
- # have not reliably cleaned up process trees and have
- # left orphaned git or ssh processes alive.
- #
- # This cleans up the subprocesses reliably but may
- # cause side effects such as possibly leaving stale
- # locks behind. Hopefully this should not be an issue
- # as long as any child processes only interact with
- # the temp directories which we control and cleanup
- # ourselves.
- #
- _kill_process_tree(process.pid)
+
+ # Some callers know that their subprocess can be
+ # gracefully terminated, make an attempt first
+ if terminate:
+ proc = psutil.Process(process.pid)
+ proc.terminate()
+
+ exit_code = None
+ try:
+ exit_code = proc.wait(20)
+ except TimeoutExpired:
+ # Did not terminate within the timeout: murder
+ _kill_process_tree(process.pid)
+
+ else:
+ # FIXME: This is a brutal but reliable approach
+ #
+ # Other variations I've tried which try SIGTERM first
+ # and then wait for child processes to exit gracefully
+ # have not reliably cleaned up process trees and have
+ # left orphaned git or ssh processes alive.
+ #
+ # This cleans up the subprocesses reliably but may
+ # cause side effects such as possibly leaving stale
+ # locks behind. Hopefully this should not be an issue
+ # as long as any child processes only interact with
+ # the temp directories which we control and cleanup
+ # ourselves.
+ #
+ _kill_process_tree(process.pid)
def suspend_proc():
if process: