Browse files

Don't attempt to wait() on event if already finished

Fixes a regression added in e757fe1, which is a race condition on a call


If the thread finishes before wait() is called then the caller would block
waiting on an event that is never set.
  • Loading branch information...
jtackaberry committed Jan 24, 2012
1 parent 4dd32e2 commit acf5a637f681d5af281450c0bf0e6da9a34d6524
Showing with 6 additions and 4 deletions.
  1. +6 −4 src/
@@ -416,15 +416,19 @@ def _finished_event_poke(self, **kwargs):
Because we're doing a test-and-create we need a mutex, and because this
is not a common operation, we avoid the (roughly 7%) overhead of
a per-instance lock. It means that all instances will synchronize on
- this mutex but because it's so rarely used I doubt there will be any
- contention on the lock.
+ this mutex but because it's so rarely accessed from multiple threads I
+ doubt there will be any contention on the lock.
if kwargs.get('set'):
with self._finished_event_lock:
+ self._finished = True
if self._finished_event:
elif 'wait' in kwargs:
with self._finished_event_lock:
+ if self._finished:
+ # Nothing to wait on, we're already done.
+ return
if not self._finished_event:
self._finished_event = threading.Event()
@@ -455,7 +459,6 @@ def finish(self, result):
return self
# store result
- self._finished = True
self._result = result
self._exception = None
# Wake any threads waiting on us
@@ -503,7 +506,6 @@ def throw(self, type=None, value=None, tb=None, aborted=False):
# custom traceback object in C code that preserves the parts of the
# stack frames needed for printing tracebacks, but discarding objects
# that would create circular references. This might be a TODO.
- self._finished = True
if type is None:
type, value, tb = sys.exc_info()
if value is None:

0 comments on commit acf5a63

Please sign in to comment.