summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Hanko <33362705+jgh-ds@users.noreply.github.com>2017-11-09 16:24:49 -0800
committerJeff Widman <jeff@jeffwidman.com>2017-11-09 16:24:49 -0800
commit4d268adf9837836f05dde5ec81be0d7bbd759e78 (patch)
treef90cf0e6e29b7a7989fb2bb0768b89e147fa5236
parentf1ccd1e7a0a0a833a1770935c60e16bf23f12356 (diff)
downloadkazoo-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.py3
-rw-r--r--kazoo/tests/test_threading_handler.py27
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)