Skip to content

Commit ac15d52

Browse files
authored
Fix potential race condition during disconnection (#2719)
When the disconnect() function is called twice in parallel it is possible that one thread deletes the self._sock reference, while the other thread will attempt to call .close() on it, leading to an AttributeError. This situation can routinely be encountered by closing the connection in a PubSubWorkerThread error handler in a blocking thread (ie. with sleep_time==None), and then calling .close() on the PubSub object. The main thread will then run into the disconnect() function, and the listener thread is woken up by the closure and will race into the disconnect() function, too. This can be fixed easily by copying the object reference before doing the None-check, similar to what we do in the redis.client.close() function.
1 parent 1ca223a commit ac15d52

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

redis/connection.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -779,20 +779,22 @@ def on_connect(self):
779779
def disconnect(self, *args):
780780
"Disconnects from the Redis server"
781781
self._parser.on_disconnect()
782-
if self._sock is None:
782+
783+
conn_sock = self._sock
784+
self._sock = None
785+
if conn_sock is None:
783786
return
784787

785788
if os.getpid() == self.pid:
786789
try:
787-
self._sock.shutdown(socket.SHUT_RDWR)
790+
conn_sock.shutdown(socket.SHUT_RDWR)
788791
except OSError:
789792
pass
790793

791794
try:
792-
self._sock.close()
795+
conn_sock.close()
793796
except OSError:
794797
pass
795-
self._sock = None
796798

797799
def _send_ping(self):
798800
"""Send PING, expect PONG in return"""

0 commit comments

Comments
 (0)