diff options
author | Steven Knight <knight@baldmt.com> | 2004-07-13 06:13:18 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2004-07-13 06:13:18 (GMT) |
commit | 9d2af963f5da83955b06353104b44ad01c86716c (patch) | |
tree | 62dbd0e4ee82caf4bf3202b8aa8e53be76a9f49a /src/engine/SCons/Taskmaster.py | |
parent | 321ac083cf44290c309b7021594c3941bfa3f82f (diff) | |
download | SCons-9d2af963f5da83955b06353104b44ad01c86716c.zip SCons-9d2af963f5da83955b06353104b44ad01c86716c.tar.gz SCons-9d2af963f5da83955b06353104b44ad01c86716c.tar.bz2 |
Make exception handling thread-safe by using sys.exc_info() instead of sys.exc_{type,value}.
Diffstat (limited to 'src/engine/SCons/Taskmaster.py')
-rw-r--r-- | src/engine/SCons/Taskmaster.py | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 7fb94aa..5bfa3d6 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -102,17 +102,19 @@ class Task: except KeyboardInterrupt: raise except SystemExit: - raise SCons.Errors.ExplicitExit(self.targets[0], sys.exc_value.code) + exc_value = sys.exc_info()[1] + raise SCons.Errors.ExplicitExit(self.targets[0], exc_value.code) except SCons.Errors.UserError: raise except SCons.Errors.BuildError: raise except: + exc_type, exc_value, exc_traceback = sys.exc_info() raise SCons.Errors.BuildError(self.targets[0], "Exception", - sys.exc_type, - sys.exc_value, - sys.exc_traceback) + exc_type, + exc_value, + exc_traceback) def get_target(self): """Fetch the target being built or updated by this task. @@ -206,6 +208,15 @@ class Task: for t in self.targets: t.postprocess() + def exc_info(self): + return self.tm.exception + + def exc_clear(self): + self.tm.exception_clear() + + def exception_set(self): + self.tm.exception_set() + def order(dependencies): @@ -229,7 +240,7 @@ class Taskmaster: self.tasker = tasker self.ready = None # the next task that is ready to be executed self.order = order - self.exception_set(None, None) + self.exception_clear() self.message = None def _find_next_ready_node(self): @@ -253,8 +264,9 @@ class Taskmaster: try: children = node.children() except SystemExit: - e = SCons.Errors.ExplicitExit(node, sys.exc_value.code) - self.exception_set(SCons.Errors.ExplicitExit, e) + exc_value = sys.exc_info()[1] + e = SCons.Errors.ExplicitExit(node, exc_value.code) + self.exception_set((SCons.Errors.ExplicitExit, e)) self.candidates.pop() self.ready = node break @@ -265,10 +277,7 @@ class Taskmaster: # children (like a child couldn't be linked in to a # BuildDir, or a Scanner threw something). Arrange to # raise the exception when the Task is "executed." - x = SCons.Errors.TaskmasterException(sys.exc_type, - sys.exc_value, - sys.exc_traceback) - self.exception_set(x) + self.exception_set() self.candidates.pop() self.ready = node break @@ -294,10 +303,7 @@ class Taskmaster: # the kids are derived (like a child couldn't be linked # from a repository). Arrange to raise the exception # when the Task is "executed." - x = SCons.Errors.TaskmasterException(sys.exc_type, - sys.exc_value, - sys.exc_traceback) - self.exception_set(x) + self.exception_set() self.candidates.pop() self.ready = node break @@ -381,10 +387,7 @@ class Taskmaster: # a child couldn't be linked in to a BuildDir when deciding # whether this node is current). Arrange to raise the # exception when the Task is "executed." - x = SCons.Errors.TaskmasterException(sys.exc_type, - sys.exc_value, - sys.exc_traceback) - self.exception_set(x) + self.exception_set() self.ready = None return task @@ -429,23 +432,21 @@ class Taskmaster: self.candidates.extend(self.pending) self.pending = [] - def exception_set(self, type, value=None): - """Record an exception type and value to raise later, at an - appropriate time.""" - self.exc_type = type - self.exc_value = value - self.exc_traceback = traceback + def exception_set(self, exception=None): + if exception is None: + exception = sys.exc_info() + self.exception = exception + self.exception_raise = self._exception_raise + + def exception_clear(self): + self.exception = (None, None, None) + self.exception_raise = self._no_exception_to_raise - def exception_raise(self): - """Raise any pending exception that was recorded while + def _no_exception_to_raise(self): + pass + + def _exception_raise(self): + """Raise a pending exception that was recorded while getting a Task ready for execution.""" - if self.exc_type: - try: - try: - raise self.exc_type, self.exc_value - except TypeError: - # exc_type was probably an instance, - # so raise it by itself. - raise self.exc_type - finally: - self.exception_set(None, None) + exc_type, exc_value = self.exception[:2] + raise exc_type, exc_value |