diff options
author | Jim Hanko <33362705+jgh-ds@users.noreply.github.com> | 2017-11-09 16:24:49 -0800 |
---|---|---|
committer | Jeff Widman <jeff@jeffwidman.com> | 2017-11-09 16:24:49 -0800 |
commit | 4d268adf9837836f05dde5ec81be0d7bbd759e78 (patch) | |
tree | f90cf0e6e29b7a7989fb2bb0768b89e147fa5236 | |
parent | f1ccd1e7a0a0a833a1770935c60e16bf23f12356 (diff) | |
download | kazoo-4d268adf9837836f05dde5ec81be0d7bbd759e78.tar.gz |
fix(core): resolve race in IAsyncResult.wait() (#487)
fix(core): resolve race in IAsyncResult.wait()
closes #485
-rw-r--r-- | kazoo/handlers/utils.py | 3 | ||||
-rw-r--r-- | kazoo/tests/test_threading_handler.py | 27 |
2 files changed, 29 insertions, 1 deletions
diff --git a/kazoo/handlers/utils.py b/kazoo/handlers/utils.py index 717c8be..e889f82 100644 --- a/kazoo/handlers/utils.py +++ b/kazoo/handlers/utils.py @@ -92,7 +92,8 @@ class AsyncResult(object): 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): diff --git a/kazoo/tests/test_threading_handler.py b/kazoo/tests/test_threading_handler.py index 119154d..2444533 100644 --- a/kazoo/tests/test_threading_handler.py +++ b/kazoo/tests/test_threading_handler.py @@ -200,6 +200,33 @@ class TestThreadingAsync(unittest.TestCase): 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) |