Skip to content

Commit c99254f

Browse files
authored
PYTHON-2334 Add regression test for gevent.Timeout compatibility (#475)
Use with statement in Semaphore.release.
1 parent 83578dc commit c99254f

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

pymongo/thread_util.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,9 @@ def acquire(self, blocking=True, timeout=None):
6060
__enter__ = acquire
6161

6262
def release(self):
63-
self._cond.acquire()
64-
self._value = self._value + 1
65-
self._cond.notify()
66-
self._cond.release()
63+
with self._cond:
64+
self._value = self._value + 1
65+
self._cond.notify()
6766

6867
def __exit__(self, t, v, tb):
6968
self.release()

test/test_client.py

+30
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,36 @@ def poller():
19441944
task.kill()
19451945
self.assertTrue(task.dead)
19461946

1947+
def test_gevent_timeout(self):
1948+
if not gevent_monkey_patched():
1949+
raise SkipTest("Must be running monkey patched by gevent")
1950+
from gevent import spawn, Timeout
1951+
client = rs_or_single_client(maxPoolSize=1)
1952+
coll = client.pymongo_test.test
1953+
coll.insert_one({})
1954+
1955+
def contentious_task():
1956+
# The 10 second timeout causes this test to fail without blocking
1957+
# forever if a bug like PYTHON-2334 is reintroduced.
1958+
with Timeout(10):
1959+
coll.find_one({'$where': delay(1)})
1960+
1961+
def timeout_task():
1962+
with Timeout(.5):
1963+
try:
1964+
coll.find_one({})
1965+
except Timeout:
1966+
pass
1967+
1968+
ct = spawn(contentious_task)
1969+
tt = spawn(timeout_task)
1970+
tt.join(15)
1971+
ct.join(15)
1972+
self.assertTrue(tt.dead)
1973+
self.assertTrue(ct.dead)
1974+
self.assertIsNone(tt.get())
1975+
self.assertIsNone(ct.get())
1976+
19471977

19481978
if __name__ == "__main__":
19491979
unittest.main()

0 commit comments

Comments
 (0)