mirror of
https://github.com/python/cpython.git
synced 2025-08-31 14:07:50 +00:00
Issue #18643: asyncio.windows_utils now reuse socket.socketpair() on Windows if
available Since Python 3.5, socket.socketpair() is now also available on Windows. Make csock blocking before calling the accept() method, and fix also a typo in an error message.
This commit is contained in:
parent
ee3e56105f
commit
f67f460242
2 changed files with 45 additions and 39 deletions
|
@ -28,49 +28,51 @@ STDOUT = subprocess.STDOUT
|
||||||
_mmap_counter = itertools.count()
|
_mmap_counter = itertools.count()
|
||||||
|
|
||||||
|
|
||||||
# Replacement for socket.socketpair()
|
if hasattr(socket, 'socketpair'):
|
||||||
|
# Since Python 3.5, socket.socketpair() is now also available on Windows
|
||||||
|
socketpair = socket.socketpair
|
||||||
|
else:
|
||||||
|
# Replacement for socket.socketpair()
|
||||||
|
def socketpair(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0):
|
||||||
|
"""A socket pair usable as a self-pipe, for Windows.
|
||||||
|
|
||||||
|
Origin: https://gist.github.com/4325783, by Geert Jansen. Public domain.
|
||||||
|
"""
|
||||||
|
if family == socket.AF_INET:
|
||||||
|
host = '127.0.0.1'
|
||||||
|
elif family == socket.AF_INET6:
|
||||||
|
host = '::1'
|
||||||
|
else:
|
||||||
|
raise ValueError("Only AF_INET and AF_INET6 socket address families "
|
||||||
|
"are supported")
|
||||||
|
if type != socket.SOCK_STREAM:
|
||||||
|
raise ValueError("Only SOCK_STREAM socket type is supported")
|
||||||
|
if proto != 0:
|
||||||
|
raise ValueError("Only protocol zero is supported")
|
||||||
|
|
||||||
def socketpair(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0):
|
# We create a connected TCP socket. Note the trick with setblocking(0)
|
||||||
"""A socket pair usable as a self-pipe, for Windows.
|
# that prevents us from having to create a thread.
|
||||||
|
lsock = socket.socket(family, type, proto)
|
||||||
Origin: https://gist.github.com/4325783, by Geert Jansen. Public domain.
|
|
||||||
"""
|
|
||||||
if family == socket.AF_INET:
|
|
||||||
host = '127.0.0.1'
|
|
||||||
elif family == socket.AF_INET6:
|
|
||||||
host = '::1'
|
|
||||||
else:
|
|
||||||
raise ValueError("Ony AF_INET and AF_INET6 socket address families "
|
|
||||||
"are supported")
|
|
||||||
if type != socket.SOCK_STREAM:
|
|
||||||
raise ValueError("Only SOCK_STREAM socket type is supported")
|
|
||||||
if proto != 0:
|
|
||||||
raise ValueError("Only protocol zero is supported")
|
|
||||||
|
|
||||||
# We create a connected TCP socket. Note the trick with setblocking(0)
|
|
||||||
# that prevents us from having to create a thread.
|
|
||||||
lsock = socket.socket(family, type, proto)
|
|
||||||
try:
|
|
||||||
lsock.bind((host, 0))
|
|
||||||
lsock.listen(1)
|
|
||||||
# On IPv6, ignore flow_info and scope_id
|
|
||||||
addr, port = lsock.getsockname()[:2]
|
|
||||||
csock = socket.socket(family, type, proto)
|
|
||||||
try:
|
try:
|
||||||
csock.setblocking(False)
|
lsock.bind((host, 0))
|
||||||
|
lsock.listen(1)
|
||||||
|
# On IPv6, ignore flow_info and scope_id
|
||||||
|
addr, port = lsock.getsockname()[:2]
|
||||||
|
csock = socket.socket(family, type, proto)
|
||||||
try:
|
try:
|
||||||
csock.connect((addr, port))
|
csock.setblocking(False)
|
||||||
except (BlockingIOError, InterruptedError):
|
try:
|
||||||
pass
|
csock.connect((addr, port))
|
||||||
ssock, _ = lsock.accept()
|
except (BlockingIOError, InterruptedError):
|
||||||
csock.setblocking(True)
|
pass
|
||||||
except:
|
csock.setblocking(True)
|
||||||
csock.close()
|
ssock, _ = lsock.accept()
|
||||||
raise
|
except:
|
||||||
finally:
|
csock.close()
|
||||||
lsock.close()
|
raise
|
||||||
return (ssock, csock)
|
finally:
|
||||||
|
lsock.close()
|
||||||
|
return (ssock, csock)
|
||||||
|
|
||||||
|
|
||||||
# Replacement for os.pipe() using handles instead of fds
|
# Replacement for os.pipe() using handles instead of fds
|
||||||
|
|
|
@ -33,6 +33,8 @@ class WinsocketpairTests(unittest.TestCase):
|
||||||
ssock, csock = windows_utils.socketpair(family=socket.AF_INET6)
|
ssock, csock = windows_utils.socketpair(family=socket.AF_INET6)
|
||||||
self.check_winsocketpair(ssock, csock)
|
self.check_winsocketpair(ssock, csock)
|
||||||
|
|
||||||
|
@unittest.skipIf(hasattr(socket, 'socketpair'),
|
||||||
|
'socket.socketpair is available')
|
||||||
@mock.patch('asyncio.windows_utils.socket')
|
@mock.patch('asyncio.windows_utils.socket')
|
||||||
def test_winsocketpair_exc(self, m_socket):
|
def test_winsocketpair_exc(self, m_socket):
|
||||||
m_socket.AF_INET = socket.AF_INET
|
m_socket.AF_INET = socket.AF_INET
|
||||||
|
@ -51,6 +53,8 @@ class WinsocketpairTests(unittest.TestCase):
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError,
|
||||||
windows_utils.socketpair, proto=1)
|
windows_utils.socketpair, proto=1)
|
||||||
|
|
||||||
|
@unittest.skipIf(hasattr(socket, 'socketpair'),
|
||||||
|
'socket.socketpair is available')
|
||||||
@mock.patch('asyncio.windows_utils.socket')
|
@mock.patch('asyncio.windows_utils.socket')
|
||||||
def test_winsocketpair_close(self, m_socket):
|
def test_winsocketpair_close(self, m_socket):
|
||||||
m_socket.AF_INET = socket.AF_INET
|
m_socket.AF_INET = socket.AF_INET
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue