Merge pull request #47 from methane/eintr

Retry when sock.recv() raises EINTR
This commit is contained in:
Charles Gordon
2015-05-12 16:06:09 -07:00
2 changed files with 31 additions and 3 deletions

View File

@@ -69,7 +69,7 @@ Best Practices:
__author__ = "Charles Gordon"
import errno
import socket
import six
@@ -1056,7 +1056,7 @@ def _readline(sock, buf):
chunks.append(buf)
last_char = buf[-1:]
buf = sock.recv(RECV_SIZE)
buf = _recv(sock, RECV_SIZE)
if not buf:
raise MemcacheUnexpectedCloseError()
@@ -1087,7 +1087,7 @@ def _readvalue(sock, buf, size):
if buf:
rlen -= len(buf)
chunks.append(buf)
buf = sock.recv(RECV_SIZE)
buf = _recv(sock, RECV_SIZE)
if not buf:
raise MemcacheUnexpectedCloseError()
@@ -1104,3 +1104,13 @@ def _readvalue(sock, buf, size):
chunks.append(buf[:rlen - 2])
return buf[rlen:], b''.join(chunks)
def _recv(sock, size):
"""sock.recv() with retry on EINTR"""
while True:
try:
return sock.recv(size)
except IOError as e:
if e.errno != errno.EINTR:
raise

View File

@@ -13,6 +13,7 @@
# limitations under the License.
import collections
import errno
import json
import socket
import unittest
@@ -627,3 +628,20 @@ class TestPrefixedPooledClient(TestPrefixedClient):
client = PooledClient(None, serializer=serializer, key_prefix=b'xyz:')
client.client_pool = pool.ObjectPool(lambda: mock_client)
return client
class TestRetryOnEINTR(unittest.TestCase):
def make_client(self, values):
client = Client(None)
client.sock = MockSocket(list(values))
return client
def test_recv(self):
client = self.make_client([
b'VALUE ',
socket.error(errno.EINTR, "Interrupted system call"),
b'key1 0 6\r\nval',
socket.error(errno.EINTR, "Interrupted system call"),
b'ue1\r\nEND\r\n',
])
tools.assert_equal(client[b'key1'], b'value1')