From 38fd8a71314dce709eaaaf5eb2db39768a5461c6 Mon Sep 17 00:00:00 2001 From: orishoshan Date: Mon, 17 Apr 2017 12:04:26 +0300 Subject: [PATCH] Issue #405: GreenSocket.accept does not notify_open (#406) greenio: GreenSocket.accept does not notify_open https://github.com/eventlet/eventlet/issues/405 --- eventlet/greenio/base.py | 5 +++- tests/greenio_test.py | 65 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/eventlet/greenio/base.py b/eventlet/greenio/base.py index c678a4d..b36d834 100644 --- a/eventlet/greenio/base.py +++ b/eventlet/greenio/base.py @@ -212,13 +212,16 @@ class GreenSocket(object): def accept(self): if self.act_non_blocking: - return self.fd.accept() + res = self.fd.accept() + notify_opened(res[0].fileno()) + return res fd = self.fd _timeout_exc = socket_timeout('timed out') while True: res = socket_accept(fd) if res is not None: client, addr = res + notify_opened(client.fileno()) set_nonblocking(client) return type(self)(client), addr self._trampoline(fd, read=True, timeout=self.gettimeout(), timeout_exc=_timeout_exc) diff --git a/tests/greenio_test.py b/tests/greenio_test.py index 6d01857..38ef191 100644 --- a/tests/greenio_test.py +++ b/tests/greenio_test.py @@ -18,6 +18,7 @@ from eventlet.hubs import get_hub from eventlet.green import select, socket, time, ssl from eventlet.support import capture_stderr, get_errno, six import tests +import tests.mock as mock def bufsized(sock, size=1): @@ -321,6 +322,70 @@ class TestGreenSocket(tests.LimitedTestCase): killer.wait() + def test_blocking_accept_mark_as_reopened(self): + evt_hub = get_hub() + with mock.patch.object(evt_hub, "mark_as_reopened") as patched_mark_as_reopened: + def connect_once(listener): + # delete/overwrite the original conn + # object, only keeping the file object around + # closing the file object should close everything + client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + client.connect(('127.0.0.1', listener.getsockname()[1])) + client.close() + + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server.bind(('127.0.0.1', 0)) + server.listen(50) + acceptlet = eventlet.spawn(connect_once, server) + conn, addr = server.accept() + conn.sendall(b'hello\n') + connfileno = conn.fileno() + conn.close() + assert patched_mark_as_reopened.called + assert patched_mark_as_reopened.call_count == 3, "3 fds were opened, but the hub was " \ + "only notified {call_count} times" \ + .format(call_count=patched_mark_as_reopened.call_count) + args, kwargs = patched_mark_as_reopened.call_args + assert args == (connfileno,), "Expected mark_as_reopened to be called " \ + "with {expected_fileno}, but it was called " \ + "with {fileno}".format(expected_fileno=connfileno, + fileno=args[0]) + server.close() + + def test_nonblocking_accept_mark_as_reopened(self): + evt_hub = get_hub() + with mock.patch.object(evt_hub, "mark_as_reopened") as patched_mark_as_reopened: + def connect_once(listener): + # delete/overwrite the original conn + # object, only keeping the file object around + # closing the file object should close everything + client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + client.connect(('127.0.0.1', listener.getsockname()[1])) + client.close() + + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server.bind(('127.0.0.1', 0)) + server.listen(50) + server.setblocking(False) + acceptlet = eventlet.spawn(connect_once, server) + out = select.select([server], [], []) + conn, addr = server.accept() + conn.sendall(b'hello\n') + connfileno = conn.fileno() + conn.close() + assert patched_mark_as_reopened.called + assert patched_mark_as_reopened.call_count == 3, "3 fds were opened, but the hub was " \ + "only notified {call_count} times" \ + .format(call_count=patched_mark_as_reopened.call_count) + args, kwargs = patched_mark_as_reopened.call_args + assert args == (connfileno,), "Expected mark_as_reopened to be called " \ + "with {expected_fileno}, but it was called " \ + "with {fileno}".format(expected_fileno=connfileno, + fileno=args[0]) + server.close() + def test_full_duplex(self): large_data = b'*' * 10 * min_buf_size() listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)