summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2015-12-16 17:53:14 +0100
committerVictor Stinner <vstinner@redhat.com>2015-12-17 10:32:23 +0100
commit58a55efad1578487f2bc8f6d3b46176f752a8489 (patch)
tree0827a97c52f18b90145c284e4e6f1edbc5b960b1
parent3ae710e70ecb3683f83b9829011de01b5d3e0bf4 (diff)
downloadeventlet-recvintoandstuff.tar.gz
gh-274: Handle blocking I/O errors in GreenSocketrecvintoandstuff
Fix recv_into(), recvfrom(), recvfrom_into() and sendto() methods of GreenSocket to handle blocking I/O errors (ex: BlockingIOError on Python 3). Even if the trampoline was called, the socket method can still fails with an I/O errors for various reasons (see manual pages of the C functions for examples). Ref: https://github.com/eventlet/eventlet/issues/274
-rw-r--r--eventlet/greenio/base.py47
1 files changed, 21 insertions, 26 deletions
diff --git a/eventlet/greenio/base.py b/eventlet/greenio/base.py
index 18799af..b5a22dc 100644
--- a/eventlet/greenio/base.py
+++ b/eventlet/greenio/base.py
@@ -304,13 +304,13 @@ class GreenSocket(object):
"makefile instead", DeprecationWarning, stacklevel=2)
return self.makefile(*args, **kw)
- def recv(self, buflen, flags=0):
+ def _recv_loop(self, recv_meth, *args):
fd = self.fd
if self.act_non_blocking:
- return fd.recv(buflen, flags)
+ return recv_meth(*args)
while True:
try:
- return fd.recv(buflen, flags)
+ return recv_meth(*args)
except socket.error as e:
if get_errno(e) in SOCKET_BLOCKING:
pass
@@ -328,35 +328,28 @@ class GreenSocket(object):
# Perhaps we should return '' instead?
raise EOFError()
- def recvfrom(self, *args):
- if not self.act_non_blocking:
- self._trampoline(self.fd, read=True, timeout=self.gettimeout(),
- timeout_exc=socket.timeout("timed out"))
- return self.fd.recvfrom(*args)
+ def recv(self, bufsize, flags=0):
+ return self._recv_loop(self.fd.recv, bufsize, flags)
- def recvfrom_into(self, *args):
- if not self.act_non_blocking:
- self._trampoline(self.fd, read=True, timeout=self.gettimeout(),
- timeout_exc=socket.timeout("timed out"))
- return self.fd.recvfrom_into(*args)
+ def recvfrom(self, bufsize, flags=0):
+ return self._recv_loop(self.fd.recvfrom, bufsize, flags)
- def recv_into(self, *args):
- if not self.act_non_blocking:
- self._trampoline(self.fd, read=True, timeout=self.gettimeout(),
- timeout_exc=socket.timeout("timed out"))
- return self.fd.recv_into(*args)
+ def recv_into(self, buffer, nbytes=0, flags=0):
+ return self._recv_loop(self.fd.recv_into, buffer, nbytes, flags)
- def send(self, data, flags=0):
- fd = self.fd
+ def recvfrom_into(self, buffer, nbytes=0, flags=0):
+ return self._recv_loop(self.fd.recvfrom_into, buffer, nbytes, flags)
+
+ def _send_loop(self, send_method, data, *args):
if self.act_non_blocking:
- return fd.send(data, flags)
+ return send_method(data, *args)
# blocking socket behavior - sends all, blocks if the buffer is full
total_sent = 0
len_data = len(data)
while 1:
try:
- total_sent += fd.send(data[total_sent:], flags)
+ total_sent += send_method(data[total_sent:], *args)
except socket.error as e:
eno = get_errno(e)
if eno == errno.ENOTCONN or eno not in SOCKET_BLOCKING:
@@ -373,16 +366,18 @@ class GreenSocket(object):
return total_sent
+ def send(self, data, flags=0):
+ return self._send_loop(self.fd.send, data, flags)
+
+ def sendto(self, data, address, flags=0):
+ return self._send_loop(self.fd.sendto, data, address, flags)
+
def sendall(self, data, flags=0):
tail = self.send(data, flags)
len_data = len(data)
while tail < len_data:
tail += self.send(data[tail:], flags)
- def sendto(self, *args):
- self._trampoline(self.fd, write=True)
- return self.fd.sendto(*args)
-
def setblocking(self, flag):
if flag:
self.act_non_blocking = False