greenio: _recv_loop behaviour with recv_into on closed sock

make sure `_recv_loop` returns the correct value when `recv_meth` is of
foo_into type (fills a buffer and returns number of bytes, not the data)

https://github.com/eventlet/eventlet/pull/353
https://github.com/onefinestay/nameko/issues/368
This commit is contained in:
David Szotten 2016-10-27 22:18:15 +01:00 committed by Sergey Shepelev
parent 7343f2e817
commit fc0e96fbc5
2 changed files with 28 additions and 6 deletions

View File

@ -318,7 +318,7 @@ class GreenSocket(object):
timeout=self.gettimeout(),
timeout_exc=socket.timeout("timed out"))
def _recv_loop(self, recv_meth, *args):
def _recv_loop(self, recv_meth, empty_val, *args):
fd = self.fd
if self.act_non_blocking:
return recv_meth(*args)
@ -340,7 +340,7 @@ class GreenSocket(object):
if get_errno(e) in SOCKET_BLOCKING:
pass
elif get_errno(e) in SOCKET_CLOSED:
return b''
return empty_val
else:
raise
@ -351,16 +351,16 @@ class GreenSocket(object):
raise EOFError()
def recv(self, bufsize, flags=0):
return self._recv_loop(self.fd.recv, bufsize, flags)
return self._recv_loop(self.fd.recv, b'', bufsize, flags)
def recvfrom(self, bufsize, flags=0):
return self._recv_loop(self.fd.recvfrom, bufsize, flags)
return self._recv_loop(self.fd.recvfrom, b'', bufsize, flags)
def recv_into(self, buffer, nbytes=0, flags=0):
return self._recv_loop(self.fd.recv_into, buffer, nbytes, flags)
return self._recv_loop(self.fd.recv_into, 0, buffer, nbytes, flags)
def recvfrom_into(self, buffer, nbytes=0, flags=0):
return self._recv_loop(self.fd.recvfrom_into, buffer, nbytes, flags)
return self._recv_loop(self.fd.recvfrom_into, 0, buffer, nbytes, flags)
def _send_loop(self, send_method, data, *args):
if self.act_non_blocking:

View File

@ -1,3 +1,4 @@
import array
import os
import shutil
import sys
@ -37,6 +38,27 @@ def test_recv_type():
assert isinstance(s, bytes)
def test_recv_into_type():
# make sure `_recv_loop` returns the correct value when `recv_meth` is of
# foo_into type (fills a buffer and returns number of bytes, not the data)
# Using threads like `test_recv_type` above.
threading = eventlet.patcher.original('threading')
addr = []
def server():
sock = eventlet.listen(('127.0.0.1', 0))
addr[:] = sock.getsockname()
eventlet.sleep(0.2)
server_thread = threading.Thread(target=server)
server_thread.start()
eventlet.sleep(0.1)
sock = eventlet.connect(tuple(addr))
buf = array.array('B', b' ')
res = sock.recv_into(buf, 1)
assert isinstance(res, int)
def test_dns_methods_are_green():
assert socket.gethostbyname is greendns.gethostbyname
assert socket.gethostbyname_ex is greendns.gethostbyname_ex