greenio: Remove sendall-like semantincs from GreenSocket.send

When a socket timeout was set the sendall-like semantics was resulting
in losing information about sent data and raising socket.timeout exception.

The previous GreenSocket.send() implementation used to call fd.send() in a
loop until all data was sent. The issue would manifest if at least one
fd.send() call succeeded and was followed by a fd.send() call that would
block and a trampoline that timed out. The client code would see
socket.timeout being raised and would rightfully assume that no data was
sent which would be incorrect.

Discussed at https://github.com/eventlet/eventlet/issues/260.
This commit is contained in:
Jakub Stasiak
2015-11-11 00:11:02 +01:00
parent 503c584a7d
commit 4656eadfa5

View File

@@ -351,28 +351,20 @@ class GreenSocket(object):
if self.act_non_blocking:
return fd.send(data, flags)
# 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)
return fd.send(data, flags)
except socket.error as e:
eno = get_errno(e)
if eno == errno.ENOTCONN or eno not in SOCKET_BLOCKING:
raise
if total_sent == len_data:
break
try:
self._trampoline(self.fd, write=True, timeout=self.gettimeout(),
timeout_exc=socket.timeout("timed out"))
except IOClosed:
raise socket.error(errno.ECONNRESET, 'Connection closed by another thread')
return total_sent
def sendall(self, data, flags=0):
tail = self.send(data, flags)
len_data = len(data)