From f9a3074a3b75f17f76cc04a693dc48a367b99861 Mon Sep 17 00:00:00 2001 From: Sergey Shepelev Date: Fri, 28 Oct 2016 01:05:03 +0300 Subject: [PATCH] convenience: listen() sets SO_REUSEPORT when available; Thanks to Zhengwei Gao From linux kernel >= 3.9, it supports the SO_REUSEPORT option that will allow multiple server socket to listen the same port https://github.com/eventlet/eventlet/pull/352 --- eventlet/convenience.py | 3 +++ tests/convenience_test.py | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/eventlet/convenience.py b/eventlet/convenience.py index d634b2c..88343a9 100644 --- a/eventlet/convenience.py +++ b/eventlet/convenience.py @@ -40,6 +40,9 @@ def listen(addr, family=socket.AF_INET, backlog=50): sock = socket.socket(family, socket.SOCK_STREAM) if sys.platform[:3] != "win": sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + if hasattr(socket, 'SO_REUSEPORT'): + # NOTE(zhengwei): linux kernel >= 3.9 + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) sock.bind(addr) sock.listen(backlog) return sock diff --git a/tests/convenience_test.py b/tests/convenience_test.py index 194699c..37b6cd4 100644 --- a/tests/convenience_test.py +++ b/tests/convenience_test.py @@ -4,14 +4,14 @@ import eventlet from eventlet import debug, event from eventlet.green import socket from eventlet.support import six -from tests import LimitedTestCase, skip_if_no_ssl +import tests certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt') private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key') -class TestServe(LimitedTestCase): +class TestServe(tests.LimitedTestCase): def setUp(self): super(TestServe, self).setUp() debug.hub_exceptions(False) @@ -111,7 +111,7 @@ class TestServe(LimitedTestCase): timeout_value="timed out") self.assertEqual(x, "timed out") - @skip_if_no_ssl + @tests.skip_if_no_ssl def test_wrap_ssl(self): server = eventlet.wrap_ssl( eventlet.listen(('localhost', 0)), @@ -132,9 +132,14 @@ class TestServe(LimitedTestCase): lsock1 = eventlet.listen(('localhost', 0)) port = lsock1.getsockname()[1] - def same_socket(): - return eventlet.listen(('localhost', port)) + if hasattr(socket, 'SO_REUSEPORT'): + lsock2 = eventlet.listen(('localhost', port)) + else: + try: + lsock2 = eventlet.listen(('localhost', port)) + assert lsock2 + lsock2.close() + except socket.error: + pass - self.assertRaises(socket.error, same_socket) lsock1.close() - assert same_socket()