Skip to content

Commit a2d687b

Browse files
tyler-willeyShaneHarvey
authored andcommitted
PYTHON-2743 Fix compatibility with gevent.Timeout (#633)
gevent.Timeout extends BaseException, not Exception. (cherry picked from commit 9c1ff6a)
1 parent d733349 commit a2d687b

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

pymongo/pool.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,7 +1221,7 @@ def connect(self, all_credentials=None):
12211221

12221222
try:
12231223
sock = _configured_socket(self.address, self.opts)
1224-
except Exception as error:
1224+
except BaseException as error:
12251225
if self.enabled_for_cmap:
12261226
listeners.publish_connection_closed(
12271227
self.address, conn_id, ConnectionClosedReason.ERROR)
@@ -1238,7 +1238,7 @@ def connect(self, all_credentials=None):
12381238

12391239
try:
12401240
sock_info.check_auth(all_credentials)
1241-
except Exception:
1241+
except BaseException:
12421242
sock_info.close_socket(ConnectionClosedReason.ERROR)
12431243
raise
12441244

@@ -1326,7 +1326,7 @@ def _get_socket(self, all_credentials):
13261326
if self._perished(sock_info):
13271327
sock_info = None
13281328
sock_info.check_auth(all_credentials)
1329-
except Exception:
1329+
except BaseException:
13301330
if sock_info:
13311331
# We checked out a socket but authentication failed.
13321332
sock_info.close_socket(ConnectionClosedReason.ERROR)

test/test_client.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,6 +2033,42 @@ def timeout_task():
20332033
self.assertIsNone(tt.get())
20342034
self.assertIsNone(ct.get())
20352035

2036+
def test_gevent_timeout_when_creating_connection(self):
2037+
if not gevent_monkey_patched():
2038+
raise SkipTest("Must be running monkey patched by gevent")
2039+
from gevent import Timeout, spawn
2040+
client = rs_or_single_client()
2041+
self.addCleanup(client.close)
2042+
coll = client.pymongo_test.test
2043+
pool = get_pool(client)
2044+
2045+
# Patch the pool to delay the connect method.
2046+
def delayed_connect(*args, **kwargs):
2047+
time.sleep(3)
2048+
return pool.__class__.connect(pool, *args, **kwargs)
2049+
2050+
pool.connect = delayed_connect
2051+
2052+
def timeout_task():
2053+
with Timeout(1):
2054+
try:
2055+
coll.find_one({})
2056+
return False
2057+
except Timeout:
2058+
return True
2059+
2060+
tt = spawn(timeout_task)
2061+
tt.join(10)
2062+
2063+
# Assert that we got our active_sockets count back
2064+
self.assertEqual(pool.active_sockets, 0)
2065+
# Assert the greenlet is dead
2066+
self.assertTrue(tt.dead)
2067+
# Assert that the Timeout was raised all the way to the try
2068+
self.assertTrue(tt.get())
2069+
# Unpatch the instance.
2070+
del pool.connect
2071+
20362072

20372073
class TestClientPool(MockClientTest):
20382074

0 commit comments

Comments
 (0)