From 4d268adf9837836f05dde5ec81be0d7bbd759e78 Mon Sep 17 00:00:00 2001 From: Jim Hanko <33362705+jgh-ds@users.noreply.github.com> Date: Thu, 9 Nov 2017 16:24:49 -0800 Subject: [PATCH] fix(core): resolve race in IAsyncResult.wait() (#487) fix(core): resolve race in IAsyncResult.wait() closes #485 --- kazoo/handlers/utils.py | 3 ++- kazoo/tests/test_threading_handler.py | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/kazoo/handlers/utils.py b/kazoo/handlers/utils.py index 717c8be4..e889f822 100644 --- a/kazoo/handlers/utils.py +++ b/kazoo/handlers/utils.py @@ -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): diff --git a/kazoo/tests/test_threading_handler.py b/kazoo/tests/test_threading_handler.py index 119154d1..24445339 100644 --- a/kazoo/tests/test_threading_handler.py +++ b/kazoo/tests/test_threading_handler.py @@ -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)