From bf122a05a21a8cc5bca314b0979f32c8026fc66e Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Thu, 31 Jan 2019 15:07:26 +0100 Subject: [PATCH] Always treat SSLError timeouts as socket timeouts (#247) Without specifically handling this case, the socket.timeout() was not raised sometimes causing the connection to lock up. In the case we hit the errno was None, so the previous if condition did not apply. Co-Authored-By: aojeagarcia --- amqp/transport.py | 4 ++++ t/unit/test_transport.py | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/amqp/transport.py b/amqp/transport.py index ea713fdb..898dbe63 100644 --- a/amqp/transport.py +++ b/amqp/transport.py @@ -376,6 +376,10 @@ def _read(self, n, initial=False, try: s = recv(n - len(rbuf)) # see note above except socket.error as exc: + # ssl.sock.read may cause a SSLerror without errno + # http://bugs.python.org/issue10272 + if isinstance(exc, SSLError) and 'timed out' in str(exc): + raise socket.timeout() # ssl.sock.read may cause ENOENT if the # operation couldn't be performed (Issue celery#1414). if exc.errno in _errnos: diff --git a/t/unit/test_transport.py b/t/unit/test_transport.py index 10a112b9..dfc398cc 100644 --- a/t/unit/test_transport.py +++ b/t/unit/test_transport.py @@ -5,7 +5,7 @@ import struct import pytest -from case import ANY, Mock, call, patch +from case import ANY, Mock, MagicMock, call, patch from amqp import transport from amqp.exceptions import UnexpectedFrame @@ -653,6 +653,22 @@ def test_write_ValueError(self): match=r'.*Socket closed.*'): self.t._write('foo') + def test_read_timeout(self): + self.t.sock = Mock(name='SSLSocket') + self.t._quick_recv = Mock(name='recv', return_value='4') + self.t._quick_recv.side_effect = socket.timeout() + self.t._read_buffer = MagicMock(return_value='AA') + with pytest.raises(socket.timeout): + self.t._read(64) + + def test_read_SSLError(self): + self.t.sock = Mock(name='SSLSocket') + self.t._quick_recv = Mock(name='recv', return_value='4') + self.t._quick_recv.side_effect = transport.SSLError('timed out') + self.t._read_buffer = MagicMock(return_value='AA') + with pytest.raises(socket.timeout): + self.t._read(64) + class test_TCPTransport: