summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2015-05-13 00:04:36 -0700
committerColin Cross <ccross@android.com>2015-05-13 11:09:38 -0700
commit31a7be561ef34c134447d92a3d391b17ecd7c790 (patch)
treeafaefd046551596817595c4dbd10534461cc0d7d
parent35de228f331101ba17bbc658c3cd910e54725517 (diff)
downloadgit-repo-31a7be561ef34c134447d92a3d391b17ecd7c790.tar.gz
Catch exceptions in project list generator
If the generator that produces per-project worker arguments raises an exception it triggers python bug http://bugs.python.org/issue8296. Rewrite the generator expression as a generator function, and catch Exceptions and KeyboardInterrupts to end the iteration. Also add a pool worker initializer to disable SIGINT to prevent KeyboardInterrupts inside multiprocessing.Pool in the worker threads causing the same problem. Fixes easy-to-reproduce hangs when hitting ctrl-c during repo forall -c echo Change-Id: Ie4a65b3e1e07a64ed6bb6ff20f3912c4326718ca
-rw-r--r--subcmds/forall.py23
1 files changed, 19 insertions, 4 deletions
diff --git a/subcmds/forall.py b/subcmds/forall.py
index 88b23fbd..6a6d30c9 100644
--- a/subcmds/forall.py
+++ b/subcmds/forall.py
@@ -20,6 +20,7 @@ import multiprocessing
20import re 20import re
21import os 21import os
22import select 22import select
23import signal
23import sys 24import sys
24import subprocess 25import subprocess
25 26
@@ -207,14 +208,12 @@ without iterating through the remaining projects.
207 208
208 os.environ['REPO_COUNT'] = str(len(projects)) 209 os.environ['REPO_COUNT'] = str(len(projects))
209 210
210 pool = multiprocessing.Pool(opt.jobs) 211 pool = multiprocessing.Pool(opt.jobs, InitWorker)
211 try: 212 try:
212 config = self.manifest.manifestProject.config 213 config = self.manifest.manifestProject.config
213 results_it = pool.imap( 214 results_it = pool.imap(
214 DoWorkWrapper, 215 DoWorkWrapper,
215 ([mirror, opt, cmd, shell, cnt, config, self._SerializeProject(p)] 216 self.ProjectArgs(projects, mirror, opt, cmd, shell, config))
216 for cnt, p in enumerate(projects))
217 )
218 pool.close() 217 pool.close()
219 for r in results_it: 218 for r in results_it:
220 rc = rc or r 219 rc = rc or r
@@ -236,12 +235,28 @@ without iterating through the remaining projects.
236 if rc != 0: 235 if rc != 0:
237 sys.exit(rc) 236 sys.exit(rc)
238 237
238 def ProjectArgs(self, projects, mirror, opt, cmd, shell, config):
239 for cnt, p in enumerate(projects):
240 try:
241 project = self._SerializeProject(p)
242 except Exception as e:
243 print('Project list error: %r' % e,
244 file=sys.stderr)
245 return
246 except KeyboardInterrupt:
247 print('Project list interrupted',
248 file=sys.stderr)
249 return
250 yield [mirror, opt, cmd, shell, cnt, config, project]
239 251
240class WorkerKeyboardInterrupt(Exception): 252class WorkerKeyboardInterrupt(Exception):
241 """ Keyboard interrupt exception for worker processes. """ 253 """ Keyboard interrupt exception for worker processes. """
242 pass 254 pass
243 255
244 256
257def InitWorker():
258 signal.signal(signal.SIGINT, signal.SIG_IGN)
259
245def DoWorkWrapper(args): 260def DoWorkWrapper(args):
246 """ A wrapper around the DoWork() method. 261 """ A wrapper around the DoWork() method.
247 262