summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorYury Selivanov <yury@magic.io>2016-09-15 19:45:07 (GMT)
committerYury Selivanov <yury@magic.io>2016-09-15 19:45:07 (GMT)
commit5587d7c071e5725d8aaf565b985441011cb1449f (patch)
tree4efe8a667f44053e0b94a3db91a33ef6d6ca48d4 /Lib
parenta1b0e7db7315ff0d8d0f8edc056f387f198cf5a1 (diff)
downloadcpython-5587d7c071e5725d8aaf565b985441011cb1449f.zip
cpython-5587d7c071e5725d8aaf565b985441011cb1449f.tar.gz
cpython-5587d7c071e5725d8aaf565b985441011cb1449f.tar.bz2
Issue #28174: Handle when SO_REUSEPORT isn't properly supported (asyncio)
Patch by Seth Michael Larson.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/asyncio/base_events.py25
-rw-r--r--Lib/test/test_asyncio/test_base_events.py11
2 files changed, 24 insertions, 12 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 8d926dc..03935ea 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -76,6 +76,17 @@ def _format_pipe(fd):
return repr(fd)
+def _set_reuseport(sock):
+ if not hasattr(socket, 'SO_REUSEPORT'):
+ raise ValueError('reuse_port not supported by socket module')
+ else:
+ try:
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
+ except OSError:
+ raise ValueError('reuse_port not supported by socket module, '
+ 'SO_REUSEPORT defined but not implemented.')
+
+
# Linux's sock.type is a bitmask that can include extra info about socket.
_SOCKET_TYPE_MASK = 0
if hasattr(socket, 'SOCK_NONBLOCK'):
@@ -873,12 +884,7 @@ class BaseEventLoop(events.AbstractEventLoop):
sock.setsockopt(
socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if reuse_port:
- if not hasattr(socket, 'SO_REUSEPORT'):
- raise ValueError(
- 'reuse_port not supported by socket module')
- else:
- sock.setsockopt(
- socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
+ _set_reuseport(sock)
if allow_broadcast:
sock.setsockopt(
socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
@@ -1001,12 +1007,7 @@ class BaseEventLoop(events.AbstractEventLoop):
sock.setsockopt(
socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
if reuse_port:
- if not hasattr(socket, 'SO_REUSEPORT'):
- raise ValueError(
- 'reuse_port not supported by socket module')
- else:
- sock.setsockopt(
- socket.SOL_SOCKET, socket.SO_REUSEPORT, True)
+ _set_reuseport(sock)
# Disable IPv4/IPv6 dual stack support (enabled by
# default on Linux) which makes a single socket
# listen on both address families.
diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py
index 0efdc20..43ebdc8 100644
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -1371,6 +1371,17 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
self.assertRaises(ValueError, self.loop.run_until_complete, f)
@patch_socket
+ def test_create_server_soreuseport_only_defined(self, m_socket):
+ m_socket.getaddrinfo = socket.getaddrinfo
+ m_socket.socket.return_value = mock.Mock()
+ m_socket.SO_REUSEPORT = -1
+
+ f = self.loop.create_server(
+ MyProto, '0.0.0.0', 0, reuse_port=True)
+
+ self.assertRaises(ValueError, self.loop.run_until_complete, f)
+
+ @patch_socket
def test_create_server_cant_bind(self, m_socket):
class Err(OSError):