OLD | NEW |
1 # Copyright 2009 Google Inc. All Rights Reserved. | 1 # Copyright 2009 Google Inc. All Rights Reserved. |
2 # | 2 # |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. |
5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at |
6 # | 6 # |
7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
8 # | 8 # |
9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 break | 464 break |
465 if not self.queued and not self.running: | 465 if not self.queued and not self.running: |
466 break | 466 break |
467 # We need to poll here otherwise Ctrl-C isn't processed. | 467 # We need to poll here otherwise Ctrl-C isn't processed. |
468 self.ready_cond.wait(10) | 468 self.ready_cond.wait(10) |
469 # Something happened: self.enqueue() or a thread terminated. Loop again. | 469 # Something happened: self.enqueue() or a thread terminated. Loop again. |
470 finally: | 470 finally: |
471 self.ready_cond.release() | 471 self.ready_cond.release() |
472 assert not self.running, 'Now guaranteed to be single-threaded' | 472 assert not self.running, 'Now guaranteed to be single-threaded' |
473 if self.exceptions: | 473 if self.exceptions: |
474 # TODO(maruel): Get back the original stack location. | 474 # To get back the stack location correctly, the raise a, b, c form must be |
475 raise self.exceptions.pop(0) | 475 # used, passing a tuple as the first argument doesn't work. |
| 476 e = self.exceptions.pop(0) |
| 477 raise e[0], e[1], e[2] |
476 if self.progress: | 478 if self.progress: |
477 self.progress.end() | 479 self.progress.end() |
478 | 480 |
479 class _Worker(threading.Thread): | 481 class _Worker(threading.Thread): |
480 """One thread to execute one WorkItem.""" | 482 """One thread to execute one WorkItem.""" |
481 def __init__(self, parent, item, args=(), kwargs=None): | 483 def __init__(self, parent, item, args=(), kwargs=None): |
482 threading.Thread.__init__(self, name=item.name or 'Worker') | 484 threading.Thread.__init__(self, name=item.name or 'Worker') |
483 self.args = args | 485 self.args = args |
484 self.kwargs = kwargs or {} | 486 self.kwargs = kwargs or {} |
485 self.item = item | 487 self.item = item |
486 self.parent = parent | 488 self.parent = parent |
487 | 489 |
488 def run(self): | 490 def run(self): |
489 """Runs in its own thread.""" | 491 """Runs in its own thread.""" |
490 logging.debug('running(%s)' % self.item.name) | 492 logging.debug('running(%s)' % self.item.name) |
491 exception = None | 493 exception = None |
492 try: | 494 try: |
493 self.item.run(*self.args, **self.kwargs) | 495 self.item.run(*self.args, **self.kwargs) |
494 except Exception, e: | 496 except Exception: |
495 # TODO(maruel): Catch exception location. | 497 # Catch exception location. |
496 exception = e | 498 exception = sys.exc_info() |
497 | 499 |
498 # This assumes the following code won't throw an exception. Bad. | 500 # This assumes the following code won't throw an exception. Bad. |
499 self.parent.ready_cond.acquire() | 501 self.parent.ready_cond.acquire() |
500 try: | 502 try: |
501 if exception: | 503 if exception: |
502 self.parent.exceptions.append(exception) | 504 self.parent.exceptions.append(exception) |
503 if self.parent.progress: | 505 if self.parent.progress: |
504 self.parent.progress.update(1) | 506 self.parent.progress.update(1) |
505 assert not self.item.name in self.parent.ran | 507 assert not self.item.name in self.parent.ran |
506 if not self.item.name in self.parent.ran: | 508 if not self.item.name in self.parent.ran: |
507 self.parent.ran.append(self.item.name) | 509 self.parent.ran.append(self.item.name) |
508 finally: | 510 finally: |
509 self.parent.ready_cond.notifyAll() | 511 self.parent.ready_cond.notifyAll() |
510 self.parent.ready_cond.release() | 512 self.parent.ready_cond.release() |
OLD | NEW |