Skip to content

Commit 369214f

Browse files
committed
Fixes garbage collection deadlock.
1 parent 4257ceb commit 369214f

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed

dev_requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
flake8>=3.9.2
22
pytest==6.2.5
3+
pytest-timeout==2.0.1
34
tox==3.24.4
45
tox-docker==3.1.0
56
invoke==1.6.0

redis/connection.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import socket
1111
import threading
1212
import warnings
13+
import weakref
1314

1415
from redis.exceptions import (
1516
AuthenticationError,
@@ -562,7 +563,7 @@ def __del__(self):
562563
pass
563564

564565
def register_connect_callback(self, callback):
565-
self._connect_callbacks.append(callback)
566+
self._connect_callbacks.append(weakref.WeakMethod(callback))
566567

567568
def clear_connect_callbacks(self):
568569
self._connect_callbacks = []
@@ -588,8 +589,10 @@ def connect(self):
588589

589590
# run any user callbacks. right now the only internal callback
590591
# is for pubsub channel/pattern resubscription
591-
for callback in self._connect_callbacks:
592-
callback(self)
592+
for ref in self._connect_callbacks:
593+
callback = ref()
594+
if callback:
595+
callback(self)
593596

594597
def _connect(self):
595598
"Create a TCP socket connection"

tests/test_pubsub.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,3 +570,15 @@ def exception_handler(ex, pubsub, thread):
570570
assert event.wait(timeout=1.0)
571571
pubsub_thread.join(timeout=1.0)
572572
assert not pubsub_thread.is_alive()
573+
574+
575+
class TestPubSubDeadlock:
576+
@pytest.mark.timeout(30, method='thread')
577+
def test_pubsub_deadlock(self, master_host):
578+
pool = redis.ConnectionPool(host=master_host)
579+
r = redis.Redis(connection_pool=pool)
580+
581+
for i in range(60):
582+
p = r.pubsub()
583+
p.subscribe("my-channel-1", "my-channel-2")
584+
pool.reset()

0 commit comments

Comments
 (0)