Skip to content

Commit 2323a0e

Browse files
committed
Fix potential race condition during disconnection
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 318b114 commit 2323a0e

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
@@ -778,20 +778,22 @@ def on_connect(self):
778778
def disconnect(self, *args):
779779
"Disconnects from the Redis server"
780780
self._parser.on_disconnect()
781-
if self._sock is None:
781+
782+
socket = self._sock
783+
self._sock = None
784+
if socket is None:
782785
return
783786

784787
if os.getpid() == self.pid:
785788
try:
786-
self._sock.shutdown(socket.SHUT_RDWR)
789+
socket.shutdown(socket.SHUT_RDWR)
787790
except OSError:
788791
pass
789792

790793
try:
791-
self._sock.close()
794+
socket.close()
792795
except OSError:
793796
pass
794-
self._sock = None
795797

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

0 commit comments

Comments
 (0)