summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Gerstel <2102431+Anthchirp@users.noreply.github.com>2023-05-01 09:21:18 +0100
committerGitHub <noreply@github.com>2023-05-01 11:21:18 +0300
commitac15d529edf2832af4c95349f6c0e9af2418448d (patch)
treec37b347f2075e7402b8ff2e3885f9abfd3bc33fd
parent1ca223a9d0df046075dddd4b572791915d657ae7 (diff)
downloadredis-py-ac15d529edf2832af4c95349f6c0e9af2418448d.tar.gz
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.
-rw-r--r--redis/connection.py10
1 files changed, 6 insertions, 4 deletions
diff --git a/redis/connection.py b/redis/connection.py
index eefdd96..8b2389c 100644
--- a/redis/connection.py
+++ b/redis/connection.py
@@ -779,20 +779,22 @@ class AbstractConnection:
def disconnect(self, *args):
"Disconnects from the Redis server"
self._parser.on_disconnect()
- if self._sock is None:
+
+ conn_sock = self._sock
+ self._sock = None
+ if conn_sock is None:
return
if os.getpid() == self.pid:
try:
- self._sock.shutdown(socket.SHUT_RDWR)
+ conn_sock.shutdown(socket.SHUT_RDWR)
except OSError:
pass
try:
- self._sock.close()
+ conn_sock.close()
except OSError:
pass
- self._sock = None
def _send_ping(self):
"""Send PING, expect PONG in return"""