Skip to content

Commit a222cfa

Browse files
committed
Added __del__ methods for classes that hold on to resources that need to be cleaned up. This should prevent resource leakage when these objects leave scope due to misuse or unhandled exceptions.
1 parent fb83cd0 commit a222cfa

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
* 2.4.10 (in development)
2+
* Added __del__ methods for classes that hold on to resources that need to
3+
be cleaned up. This should prevent resource leakage when these objects
4+
leave scope due to misuse or unhandled exceptions.
25
* Added the ECHO command for completeness.
36
* Fixed a bug where attempting to subscribe to a PubSub channel of a Redis
47
server that's down would blow out the stack. Fixes #179 and #195. Thanks

redis/client.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,22 @@ def __init__(self, connection_pool, shard_hint=None):
11691169
('subscribe', 'psubscribe', 'unsubscribe', 'punsubscribe')
11701170
)
11711171

1172+
def __del__(self):
1173+
try:
1174+
# if this object went out of scope prior to shutting down
1175+
# subscriptions, close the connection manually before
1176+
# returning it to the connection pool
1177+
if self.connection and (self.channels or self.patterns):
1178+
self.connection.disconnect()
1179+
self.reset()
1180+
except:
1181+
pass
1182+
1183+
def reset(self):
1184+
if self.connection:
1185+
self.connection_pool.release(self.connection)
1186+
self.connection = None
1187+
11721188
def execute_command(self, *args, **kwargs):
11731189
"Execute a publish/subscribe command"
11741190
if self.connection is None:
@@ -1202,8 +1218,7 @@ def parse_response(self):
12021218
# if we've just unsubscribed from the remaining channels,
12031219
# release the connection back to the pool
12041220
if not self.subscription_count:
1205-
self.connection_pool.release(self.connection)
1206-
self.connection = None
1221+
self.reset()
12071222
return response
12081223

12091224
def psubscribe(self, patterns):
@@ -1309,6 +1324,12 @@ def __enter__(self):
13091324
def __exit__(self, exc_type, exc_value, traceback):
13101325
self.reset()
13111326

1327+
def __del__(self):
1328+
try:
1329+
self.reset()
1330+
except:
1331+
pass
1332+
13121333
def reset(self):
13131334
self.command_stack = []
13141335
# make sure to reset the connection state in the event that we were

redis/connection.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@
44
from redis.exceptions import ConnectionError, ResponseError, InvalidResponse
55

66
class PythonParser(object):
7+
"Plain Python parsing class"
78
def __init__(self):
89
self._fp = None
910

11+
def __del__(self):
12+
try:
13+
self.on_disconnect()
14+
except:
15+
pass
16+
1017
def on_connect(self, connection):
1118
"Called when the socket connects"
1219
self._fp = connection._sock.makefile('r')
@@ -68,6 +75,13 @@ def read_response(self):
6875
raise InvalidResponse("Protocol Error")
6976

7077
class HiredisParser(object):
78+
"Parser class for connections using Hiredis"
79+
def __del__(self):
80+
try:
81+
self.on_disconnect()
82+
except:
83+
pass
84+
7185
def on_connect(self, connection):
7286
self._sock = connection._sock
7387
self._reader = hiredis.Reader(
@@ -119,6 +133,12 @@ def __init__(self, host='localhost', port=6379, db=0, password=None,
119133
self._sock = None
120134
self._parser = parser_class()
121135

136+
def __del__(self):
137+
try:
138+
self.disconnect()
139+
except:
140+
pass
141+
122142
def connect(self):
123143
"Connects to the Redis server if not already connected"
124144
if self._sock:
@@ -148,7 +168,6 @@ def _error_message(self, exception):
148168
return "Error %s connecting %s:%s. %s." % \
149169
(exception.args[0], self.host, self.port, exception.args[1])
150170

151-
152171
def on_connect(self):
153172
"Initialize the connection, authenticate and select a database"
154173
self._parser.on_connect(self)

0 commit comments

Comments
 (0)