Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(795)

Unified Diff: gclient_utils.py

Issue 14759006: Kill subprocesses on KeyboardInterrupt. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Fix nit. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gclient.py ('k') | tests/gclient_utils_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gclient_utils.py
diff --git a/gclient_utils.py b/gclient_utils.py
index 041813b0d164322a816669b175e3f7259ac109cb..bf9803e86f3552c151d788cec8cf354233dc432a 100644
--- a/gclient_utils.py
+++ b/gclient_utils.py
@@ -323,6 +323,56 @@ def MakeFileAnnotated(fileobj, include_zero=False):
return Annotated(fileobj)
+GCLIENT_CHILDREN = []
+GCLIENT_CHILDREN_LOCK = threading.Lock()
+
+
+class GClientChildren(object):
+ @staticmethod
+ def add(popen_obj):
+ with GCLIENT_CHILDREN_LOCK:
+ GCLIENT_CHILDREN.append(popen_obj)
+
+ @staticmethod
+ def remove(popen_obj):
+ with GCLIENT_CHILDREN_LOCK:
+ GCLIENT_CHILDREN.remove(popen_obj)
+
+ @staticmethod
+ def _attemptToKillChildren():
+ global GCLIENT_CHILDREN
+ with GCLIENT_CHILDREN_LOCK:
+ zombies = [c for c in GCLIENT_CHILDREN if c.poll() is None]
+
+ for zombie in zombies:
+ try:
+ zombie.kill()
+ except OSError:
+ pass
+
+ with GCLIENT_CHILDREN_LOCK:
+ GCLIENT_CHILDREN = [k for k in GCLIENT_CHILDREN if k.poll() is not None]
+
+ @staticmethod
+ def _areZombies():
+ with GCLIENT_CHILDREN_LOCK:
+ return bool(GCLIENT_CHILDREN)
+
+ @staticmethod
+ def KillAllRemainingChildren():
+ GClientChildren._attemptToKillChildren()
+
+ if GClientChildren._areZombies():
+ time.sleep(0.5)
+ GClientChildren._attemptToKillChildren()
+
+ with GCLIENT_CHILDREN_LOCK:
+ if GCLIENT_CHILDREN:
+ print >> sys.stderr, 'Could not kill the following subprocesses:'
+ for zombie in GCLIENT_CHILDREN:
+ print >> sys.stderr, ' ', zombie.pid
+
+
def CheckCallAndFilter(args, stdout=None, filter_fn=None,
print_stdout=None, call_filter_on_first_line=False,
**kwargs):
@@ -344,6 +394,8 @@ def CheckCallAndFilter(args, stdout=None, filter_fn=None,
args, bufsize=0, stdout=subprocess2.PIPE, stderr=subprocess2.STDOUT,
**kwargs)
+ GClientChildren.add(kid)
+
# Do a flush of stdout before we begin reading from the subprocess2's stdout
stdout.flush()
@@ -375,6 +427,11 @@ def CheckCallAndFilter(args, stdout=None, filter_fn=None,
if len(in_line):
filter_fn(in_line)
rv = kid.wait()
+
+ # Don't put this in a 'finally,' since the child may still run if we get an
+ # exception.
+ GClientChildren.remove(kid)
+
except KeyboardInterrupt:
print >> sys.stderr, 'Failed while running "%s"' % ' '.join(args)
raise
@@ -657,6 +714,7 @@ class ExecutionQueue(object):
self.index = index
self.args = args
self.kwargs = kwargs
+ self.daemon = True
def run(self):
"""Runs in its own thread."""
@@ -664,18 +722,23 @@ class ExecutionQueue(object):
work_queue = self.kwargs['work_queue']
try:
self.item.run(*self.args, **self.kwargs)
+ except KeyboardInterrupt:
+ logging.info('Caught KeyboardInterrupt in thread %s' % self.item.name)
+ logging.info(str(sys.exc_info()))
+ work_queue.exceptions.put(sys.exc_info())
+ raise
except Exception:
# Catch exception location.
logging.info('Caught exception in thread %s' % self.item.name)
logging.info(str(sys.exc_info()))
work_queue.exceptions.put(sys.exc_info())
- logging.info('_Worker.run(%s) done' % self.item.name)
-
- work_queue.ready_cond.acquire()
- try:
- work_queue.ready_cond.notifyAll()
finally:
- work_queue.ready_cond.release()
+ logging.info('_Worker.run(%s) done' % self.item.name)
+ work_queue.ready_cond.acquire()
+ try:
+ work_queue.ready_cond.notifyAll()
+ finally:
+ work_queue.ready_cond.release()
def GetEditor(git, git_editor=None):
« no previous file with comments | « gclient.py ('k') | tests/gclient_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698