Skip to content

Commit 254c8c0

Browse files
authored
Fix possible pipeline connections leak (#3104)
* Update cluster.py When Executing "n.write()" may generate some unknown errors(e.g. DataError), which could result in the connection not being released. * Update cluster.py * Update cluster.py release connection move to "try...finally" * Update cluster.py fix the linters * fix problems of code review
1 parent df29566 commit 254c8c0

File tree

1 file changed

+28
-26
lines changed

1 file changed

+28
-26
lines changed

redis/cluster.py

+28-26
Original file line numberDiff line numberDiff line change
@@ -2166,32 +2166,34 @@ def _send_cluster_commands(
21662166
# we dont' multiplex on the sockets as they come available,
21672167
# but that shouldn't make too much difference.
21682168
node_commands = nodes.values()
2169-
for n in node_commands:
2170-
n.write()
2171-
2172-
for n in node_commands:
2173-
n.read()
2174-
2175-
# release all of the redis connections we allocated earlier
2176-
# back into the connection pool.
2177-
# we used to do this step as part of a try/finally block,
2178-
# but it is really dangerous to
2179-
# release connections back into the pool if for some
2180-
# reason the socket has data still left in it
2181-
# from a previous operation. The write and
2182-
# read operations already have try/catch around them for
2183-
# all known types of errors including connection
2184-
# and socket level errors.
2185-
# So if we hit an exception, something really bad
2186-
# happened and putting any oF
2187-
# these connections back into the pool is a very bad idea.
2188-
# the socket might have unread buffer still sitting in it,
2189-
# and then the next time we read from it we pass the
2190-
# buffered result back from a previous command and
2191-
# every single request after to that connection will always get
2192-
# a mismatched result.
2193-
for n in nodes.values():
2194-
n.connection_pool.release(n.connection)
2169+
try:
2170+
node_commands = nodes.values()
2171+
for n in node_commands:
2172+
n.write()
2173+
2174+
for n in node_commands:
2175+
n.read()
2176+
finally:
2177+
# release all of the redis connections we allocated earlier
2178+
# back into the connection pool.
2179+
# we used to do this step as part of a try/finally block,
2180+
# but it is really dangerous to
2181+
# release connections back into the pool if for some
2182+
# reason the socket has data still left in it
2183+
# from a previous operation. The write and
2184+
# read operations already have try/catch around them for
2185+
# all known types of errors including connection
2186+
# and socket level errors.
2187+
# So if we hit an exception, something really bad
2188+
# happened and putting any oF
2189+
# these connections back into the pool is a very bad idea.
2190+
# the socket might have unread buffer still sitting in it,
2191+
# and then the next time we read from it we pass the
2192+
# buffered result back from a previous command and
2193+
# every single request after to that connection will always get
2194+
# a mismatched result.
2195+
for n in nodes.values():
2196+
n.connection_pool.release(n.connection)
21952197

21962198
# if the response isn't an exception it is a
21972199
# valid response from the node

0 commit comments

Comments
 (0)