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
This commit is contained in:
Sergey Shepelev 2016-10-28 01:05:03 +03:00
parent fc0e96fbc5
commit f9a3074a3b
2 changed files with 15 additions and 7 deletions

View File

@ -40,6 +40,9 @@ def listen(addr, family=socket.AF_INET, backlog=50):
sock = socket.socket(family, socket.SOCK_STREAM) sock = socket.socket(family, socket.SOCK_STREAM)
if sys.platform[:3] != "win": if sys.platform[:3] != "win":
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 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.bind(addr)
sock.listen(backlog) sock.listen(backlog)
return sock return sock

View File

@ -4,14 +4,14 @@ import eventlet
from eventlet import debug, event from eventlet import debug, event
from eventlet.green import socket from eventlet.green import socket
from eventlet.support import six 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') 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') private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
class TestServe(LimitedTestCase): class TestServe(tests.LimitedTestCase):
def setUp(self): def setUp(self):
super(TestServe, self).setUp() super(TestServe, self).setUp()
debug.hub_exceptions(False) debug.hub_exceptions(False)
@ -111,7 +111,7 @@ class TestServe(LimitedTestCase):
timeout_value="timed out") timeout_value="timed out")
self.assertEqual(x, "timed out") self.assertEqual(x, "timed out")
@skip_if_no_ssl @tests.skip_if_no_ssl
def test_wrap_ssl(self): def test_wrap_ssl(self):
server = eventlet.wrap_ssl( server = eventlet.wrap_ssl(
eventlet.listen(('localhost', 0)), eventlet.listen(('localhost', 0)),
@ -132,9 +132,14 @@ class TestServe(LimitedTestCase):
lsock1 = eventlet.listen(('localhost', 0)) lsock1 = eventlet.listen(('localhost', 0))
port = lsock1.getsockname()[1] port = lsock1.getsockname()[1]
def same_socket(): if hasattr(socket, 'SO_REUSEPORT'):
return eventlet.listen(('localhost', port)) 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() lsock1.close()
assert same_socket()