From 69beec6ca67501fc1182d533b940c5fb79b61bdf Mon Sep 17 00:00:00 2001 From: "A. Jesse Jiryu Davis" Date: Wed, 17 Dec 2014 11:25:57 -0500 Subject: [PATCH] PYTHON-799 RS client's close_cursor shouldn't lock client. We still take a lock in Pool.get_socket and maybe_return_socket, but in my tests it doesn't seem possible to deadlock the GC from Pool. --- pymongo/mongo_replica_set_client.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/pymongo/mongo_replica_set_client.py b/pymongo/mongo_replica_set_client.py index 1db3f5ad1..3a02fd1dc 100644 --- a/pymongo/mongo_replica_set_client.py +++ b/pymongo/mongo_replica_set_client.py @@ -1815,8 +1815,25 @@ class MongoReplicaSetClient(common.BaseObject): if not isinstance(cursor_id, (int, long)): raise TypeError("cursor_id must be an instance of (int, long)") - self._send_message(message.kill_cursors([cursor_id]), - _connection_to_use=_conn_id) + member = self.__get_rs_state().get(_conn_id) + + # We can't risk taking the lock to reconnect if we're being called + # from Cursor.__del__, see PYTHON-799. + if not member: + warnings.warn("not connected, couldn't close cursor", + stacklevel=2) + return + + _, kill_cursors_msg = message.kill_cursors([cursor_id]) + sock_info = self.__socket(member) + try: + try: + sock_info.sock.sendall(kill_cursors_msg) + except: + sock_info.close() + raise + finally: + member.maybe_return_socket(sock_info) def server_info(self): """Get information about the MongoDB primary we're connected to.