Skip to content
This repository was archived by the owner on Nov 23, 2017. It is now read-only.

Commit 10ca0f3

Browse files
committed
Detach socket in create_server, create_connection, and other APIs
1 parent e3fed68 commit 10ca0f3

File tree

3 files changed

+17
-5
lines changed

3 files changed

+17
-5
lines changed

Diff for: asyncio/base_events.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ def _set_reuseport(sock):
8787
'SO_REUSEPORT defined but not implemented.')
8888

8989

90+
def _copy_and_detach_socket(sock):
91+
new_sock = socket.socket(sock.family, sock.type, sock.proto, sock.fileno())
92+
sock.detach()
93+
return new_sock
94+
95+
9096
# Linux's sock.type is a bitmask that can include extra info about socket.
9197
_SOCKET_TYPE_MASK = 0
9298
if hasattr(socket, 'SOCK_NONBLOCK'):
@@ -768,9 +774,11 @@ def create_connection(self, protocol_factory, host=None, port=None, *,
768774
raise OSError('Multiple exceptions: {}'.format(
769775
', '.join(str(exc) for exc in exceptions)))
770776

771-
elif sock is None:
772-
raise ValueError(
773-
'host and port was not specified and no sock specified')
777+
else:
778+
if sock is None:
779+
raise ValueError(
780+
'host and port was not specified and no sock specified')
781+
sock = _copy_and_detach_socket(sock)
774782

775783
transport, protocol = yield from self._create_connection_transport(
776784
sock, protocol_factory, ssl, server_hostname)
@@ -827,6 +835,7 @@ def create_datagram_endpoint(self, protocol_factory,
827835
raise ValueError(
828836
'socket modifier keyword arguments can not be used '
829837
'when sock is specified. ({})'.format(problems))
838+
sock = _copy_and_detach_socket(sock)
830839
sock.setblocking(False)
831840
r_addr = None
832841
else:
@@ -1024,6 +1033,7 @@ def create_server(self, protocol_factory, host=None, port=None,
10241033
else:
10251034
if sock is None:
10261035
raise ValueError('Neither host/port nor sock were specified')
1036+
sock = _copy_and_detach_socket(sock)
10271037
sockets = [sock]
10281038

10291039
server = Server(self, sockets)
@@ -1045,6 +1055,7 @@ def connect_accepted_socket(self, protocol_factory, sock, *, ssl=None):
10451055
This method is a coroutine. When completed, the coroutine
10461056
returns a (transport, protocol) pair.
10471057
"""
1058+
sock = _copy_and_detach_socket(sock)
10481059
transport, protocol = yield from self._create_connection_transport(
10491060
sock, protocol_factory, ssl, '', server_side=True)
10501061
if self._debug:

Diff for: tests/test_events.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1240,11 +1240,12 @@ def connection_made(self, transport):
12401240
sock_ob = socket.socket(type=socket.SOCK_STREAM)
12411241
sock_ob.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
12421242
sock_ob.bind(('0.0.0.0', 0))
1243+
sock_ob_fd = sock_ob.fileno()
12431244

12441245
f = self.loop.create_server(TestMyProto, sock=sock_ob)
12451246
server = self.loop.run_until_complete(f)
12461247
sock = server.sockets[0]
1247-
self.assertIs(sock, sock_ob)
1248+
self.assertEqual(sock.fileno(), sock_ob_fd)
12481249

12491250
host, port = sock.getsockname()
12501251
self.assertEqual(host, '0.0.0.0')

Diff for: tests/test_streams.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ def start(self):
582582
asyncio.start_server(self.handle_client,
583583
sock=sock,
584584
loop=self.loop))
585-
return sock.getsockname()
585+
return self.server.sockets[0].getsockname()
586586

587587
def handle_client_callback(self, client_reader, client_writer):
588588
self.loop.create_task(self.handle_client(client_reader,

0 commit comments

Comments
 (0)