From ef54bf06f7d0024b066827903887fec2a1b07fe9 Mon Sep 17 00:00:00 2001 From: Aliaksei Urbanski Date: Wed, 23 Oct 2019 21:27:47 +0300 Subject: [PATCH] Fix 'NoneType' object has no attribute 'can_read' (#1107) The root cause of the issue is that the connection can be erased during an execution of self._receive_one(c). So c.connection should be checked before every iteration, not only before the first one. --- kombu/transport/redis.py | 5 ++--- t/unit/transport/test_redis.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/kombu/transport/redis.py b/kombu/transport/redis.py index 82eacd37..005ef02c 100644 --- a/kombu/transport/redis.py +++ b/kombu/transport/redis.py @@ -684,9 +684,8 @@ class Channel(virtual.Channel): ret.append(self._receive_one(c)) except Empty: pass - if c.connection is not None: - while c.connection.can_read(timeout=0): - ret.append(self._receive_one(c)) + while c.connection is not None and c.connection.can_read(timeout=0): + ret.append(self._receive_one(c)) return any(ret) def _receive_one(self, c): diff --git a/t/unit/transport/test_redis.py b/t/unit/transport/test_redis.py index 520731bd..2646e6b2 100644 --- a/t/unit/transport/test_redis.py +++ b/t/unit/transport/test_redis.py @@ -807,6 +807,18 @@ class TestRedisChannel(unittest.TestCase): assert self.channel._receive_one(self.channel.subclient) is None + def test_receive_connection_has_gone(self): + def _receive_one(c): + c.connection = None + _receive_one.called = True + return True + + _receive_one.called = False + self.channel._receive_one = _receive_one + + assert self.channel._receive() + assert _receive_one.called + def test_brpop_read_raises(self): c = self.channel.client = Mock() c.parse_response.side_effect = KeyError('foo')