Skip to content

Commit

Permalink
fix(core): resolve race in IAsyncResult.wait() (#487)
Browse files Browse the repository at this point in the history
fix(core): resolve race in IAsyncResult.wait()

closes #485
  • Loading branch information
jgh-ds authored and jeffwidman committed Nov 10, 2017
1 parent f1ccd1e commit 4d268ad
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
3 changes: 2 additions & 1 deletion kazoo/handlers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ def get_nowait(self):
def wait(self, timeout=None):
"""Block until the instance is ready."""
with self._condition:
self._condition.wait(timeout)
if not self.ready():
self._condition.wait(timeout)
return self._exception is not _NONE

def rawlink(self, callback):
Expand Down
27 changes: 27 additions & 0 deletions kazoo/tests/test_threading_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,33 @@ def wait_for_val():
eq_(lst, [True])
th.join()

def test_wait_race(self):
"""Test that there is no race condition in `IAsyncResult.wait()`.
Guards against the reappearance of:
https://github.com/python-zk/kazoo/issues/485
"""
mock_handler = mock.Mock()
async_result = self._makeOne(mock_handler)

async_result.set("immediate")

cv = threading.Event()

def wait_for_val():
# NB: should not sleep
async_result.wait(20)
cv.set()
th = threading.Thread(target=wait_for_val)
th.daemon = True
th.start()

# if the wait() didn't sleep (correctly), cv will be set quickly
# if it did sleep, the cv will not be set yet and this will timeout
cv.wait(10)
eq_(cv.is_set(), True)
th.join()

def test_set_before_wait(self):
mock_handler = mock.Mock()
async_result = self._makeOne(mock_handler)
Expand Down

0 comments on commit 4d268ad

Please sign in to comment.