convenience: SO_REUSEPORT is not available on WSL platform (Linux on Windows)
https://github.com/eventlet/eventlet/issues/380 https://github.com/eventlet/eventlet/issues/418
This commit is contained in:
parent
0ec4df6cbe
commit
09e166bfbd
|
@ -3,6 +3,7 @@ import warnings
|
|||
|
||||
from eventlet import greenpool
|
||||
from eventlet import greenthread
|
||||
from eventlet import support
|
||||
from eventlet.green import socket
|
||||
from eventlet.support import greenlets as greenlet
|
||||
|
||||
|
@ -26,6 +27,10 @@ class ReuseRandomPortWarning(Warning):
|
|||
pass
|
||||
|
||||
|
||||
class ReusePortUnavailableWarning(Warning):
|
||||
pass
|
||||
|
||||
|
||||
def listen(addr, family=socket.AF_INET, backlog=50, reuse_addr=True, reuse_port=None):
|
||||
"""Convenience function for opening server sockets. This
|
||||
socket can be used in :func:`~eventlet.serve` or a custom ``accept()`` loop.
|
||||
|
@ -55,7 +60,20 @@ def listen(addr, family=socket.AF_INET, backlog=50, reuse_addr=True, reuse_port=
|
|||
reuse_port = True
|
||||
if reuse_port and hasattr(socket, 'SO_REUSEPORT'):
|
||||
# NOTE(zhengwei): linux kernel >= 3.9
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
||||
try:
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
||||
except OSError as ex:
|
||||
if support.get_errno(ex) in (22, 92):
|
||||
# A famous platform defines unsupported socket option.
|
||||
# https://github.com/eventlet/eventlet/issues/380
|
||||
# https://github.com/eventlet/eventlet/issues/418
|
||||
warnings.warn(
|
||||
'''socket.SO_REUSEPORT is defined but not supported.
|
||||
On Windows: known bug, wontfix.
|
||||
On other systems: please comment in the issue linked below.
|
||||
More information: https://github.com/eventlet/eventlet/issues/380''',
|
||||
ReusePortUnavailableWarning, stacklevel=3)
|
||||
|
||||
sock.bind(addr)
|
||||
sock.listen(backlog)
|
||||
return sock
|
||||
|
|
|
@ -6,6 +6,7 @@ from eventlet import convenience, debug
|
|||
from eventlet.green import socket
|
||||
from eventlet.support import six
|
||||
import tests
|
||||
import tests.mock
|
||||
|
||||
|
||||
certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
|
||||
|
@ -167,3 +168,29 @@ def test_reuse_random_port_warning():
|
|||
eventlet.listen(('localhost', 0), reuse_port=True).close()
|
||||
assert len(w) == 1
|
||||
assert issubclass(w[0].category, convenience.ReuseRandomPortWarning)
|
||||
|
||||
|
||||
@tests.skip_unless(hasattr(socket, 'SO_REUSEPORT'))
|
||||
def test_reuseport_oserror():
|
||||
# https://github.com/eventlet/eventlet/issues/380
|
||||
# https://github.com/eventlet/eventlet/issues/418
|
||||
err22 = OSError(22, 'Invalid argument')
|
||||
|
||||
sock1 = eventlet.listen(('localhost', 0))
|
||||
addr = sock1.getsockname()
|
||||
sock1.close()
|
||||
|
||||
original_socket_init = socket.socket.__init__
|
||||
|
||||
def patched(self, *a, **kw):
|
||||
original_socket_init(self, *a, **kw)
|
||||
self.setsockopt = tests.mock.Mock(side_effect=err22)
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
try:
|
||||
socket.socket.__init__ = patched
|
||||
eventlet.listen(addr, reuse_addr=False, reuse_port=True).close()
|
||||
finally:
|
||||
socket.socket.__init__ = original_socket_init
|
||||
assert len(w) == 1
|
||||
assert issubclass(w[0].category, convenience.ReusePortUnavailableWarning)
|
||||
|
|
Loading…
Reference in New Issue