-
Notifications
You must be signed in to change notification settings - Fork 249
Description
UniversalEvent
(and consequently UniversalResult
) has a race condition in the _unblock_waiters()
method. Since discarding a future object from the _waiting
set is done without holding the lock[1][2][3], it may occur at iteration time in the _unblock_waiters()
method. As a result, RuntimeError
will be raised.
Since this is a multi-threaded issue, it cannot be reliably reproduced. Instead, below is synthetic code that demonstrates that behavior.
items = {1, 2, 3}
for item in items: # raises RuntimeError
items.discard(item + 1)
The quickest solution is to copy the set before iterating.
Note that this is actually #352. The fixes were not sufficient - they reduce the reproducibility of the issue, but they do not fix the issue itself. Getting a reference to the set and calling its method are different operations, and context switching can happen in between.