From f67f4602426be4de9b0d0124cb99ecc5edbd70aa Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 14 Oct 2014 22:56:25 +0200 Subject: [PATCH] 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. --- Lib/asyncio/windows_utils.py | 80 +++++++++++---------- Lib/test/test_asyncio/test_windows_utils.py | 4 ++ 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/Lib/asyncio/windows_utils.py b/Lib/asyncio/windows_utils.py index f7f2f3580ad..1155a77f346 100644 --- a/Lib/asyncio/windows_utils.py +++ b/Lib/asyncio/windows_utils.py @@ -28,49 +28,51 @@ STDOUT = subprocess.STDOUT _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): - """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("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) + # 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: - 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: - csock.connect((addr, port)) - except (BlockingIOError, InterruptedError): - pass - ssock, _ = lsock.accept() - csock.setblocking(True) - except: - csock.close() - raise - finally: - lsock.close() - return (ssock, csock) + csock.setblocking(False) + try: + csock.connect((addr, port)) + except (BlockingIOError, InterruptedError): + pass + csock.setblocking(True) + ssock, _ = lsock.accept() + except: + csock.close() + raise + finally: + lsock.close() + return (ssock, csock) # Replacement for os.pipe() using handles instead of fds diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py index 7ea3a6d380b..3e7a211ea74 100644 --- a/Lib/test/test_asyncio/test_windows_utils.py +++ b/Lib/test/test_asyncio/test_windows_utils.py @@ -33,6 +33,8 @@ class WinsocketpairTests(unittest.TestCase): ssock, csock = windows_utils.socketpair(family=socket.AF_INET6) self.check_winsocketpair(ssock, csock) + @unittest.skipIf(hasattr(socket, 'socketpair'), + 'socket.socketpair is available') @mock.patch('asyncio.windows_utils.socket') def test_winsocketpair_exc(self, m_socket): m_socket.AF_INET = socket.AF_INET @@ -51,6 +53,8 @@ class WinsocketpairTests(unittest.TestCase): self.assertRaises(ValueError, windows_utils.socketpair, proto=1) + @unittest.skipIf(hasattr(socket, 'socketpair'), + 'socket.socketpair is available') @mock.patch('asyncio.windows_utils.socket') def test_winsocketpair_close(self, m_socket): m_socket.AF_INET = socket.AF_INET