summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Shepelev <temotor@gmail.com>2017-05-31 16:50:41 +0300
committerSergey Shepelev <temotor@gmail.com>2017-06-02 20:43:23 +0300
commit09e166bfbd6ba6f52477a7ae1c421dcabd1f004c (patch)
tree8c2f4cd64e2cc27a73efb50ad2a8ffb4f38363a2
parent0ec4df6cbe1771493d112c3f893b8ac1d89b5dbf (diff)
downloadeventlet-09e166bfbd6ba6f52477a7ae1c421dcabd1f004c.tar.gz
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
-rw-r--r--eventlet/convenience.py20
-rw-r--r--tests/convenience_test.py27
2 files changed, 46 insertions, 1 deletions
diff --git a/eventlet/convenience.py b/eventlet/convenience.py
index 560de23..7453ff8 100644
--- a/eventlet/convenience.py
+++ b/eventlet/convenience.py
@@ -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
diff --git a/tests/convenience_test.py b/tests/convenience_test.py
index 6f996fe..32e74e3 100644
--- a/tests/convenience_test.py
+++ b/tests/convenience_test.py
@@ -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)