From c99254fe974110f6749028e8693b9c820349ff09 Mon Sep 17 00:00:00 2001 From: Shane Harvey Date: Wed, 29 Jul 2020 18:05:18 -0700 Subject: [PATCH] PYTHON-2334 Add regression test for gevent.Timeout compatibility (#475) Use with statement in Semaphore.release. --- pymongo/thread_util.py | 7 +++---- test/test_client.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/pymongo/thread_util.py b/pymongo/thread_util.py index 0cf0a127f2..3dac4e25fa 100644 --- a/pymongo/thread_util.py +++ b/pymongo/thread_util.py @@ -60,10 +60,9 @@ def acquire(self, blocking=True, timeout=None): __enter__ = acquire def release(self): - self._cond.acquire() - self._value = self._value + 1 - self._cond.notify() - self._cond.release() + with self._cond: + self._value = self._value + 1 + self._cond.notify() def __exit__(self, t, v, tb): self.release() diff --git a/test/test_client.py b/test/test_client.py index 5333fc35ff..19ea1375c2 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -1944,6 +1944,36 @@ def poller(): task.kill() self.assertTrue(task.dead) + def test_gevent_timeout(self): + if not gevent_monkey_patched(): + raise SkipTest("Must be running monkey patched by gevent") + from gevent import spawn, Timeout + client = rs_or_single_client(maxPoolSize=1) + coll = client.pymongo_test.test + coll.insert_one({}) + + def contentious_task(): + # The 10 second timeout causes this test to fail without blocking + # forever if a bug like PYTHON-2334 is reintroduced. + with Timeout(10): + coll.find_one({'$where': delay(1)}) + + def timeout_task(): + with Timeout(.5): + try: + coll.find_one({}) + except Timeout: + pass + + ct = spawn(contentious_task) + tt = spawn(timeout_task) + tt.join(15) + ct.join(15) + self.assertTrue(tt.dead) + self.assertTrue(ct.dead) + self.assertIsNone(tt.get()) + self.assertIsNone(ct.get()) + if __name__ == "__main__": unittest.main()