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: