From c2fd5de1c4858bc9dd8fd3591d9b5065629fd8d6 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 27 Oct 2017 10:27:04 +0200 Subject: [PATCH 1/2] Fix tests in test_asyncore that are affected by a bug in Cygwin: * connect()-ing an AF_UNIX socket can hang indefinitely if the server is not actively accept()-ing connections; see https://cygwin.com/ml/cygwin/2017-01/msg00054.html This issue is worked around explicitly in the tests, but not generally in asyncore (as the only known general workaround breaks SO_PEERCRED queries). It's also something of a corner-case which won't affect non-test code often. --- Lib/test/test_asyncore.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index ee0c3b371f8be01..27fb84d33d435c0 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -97,6 +97,12 @@ def bind_af_aware(sock, addr): sock.bind(addr) +def setsock_no_peercred(sock): + if sys.platform == 'cygwin' and sock.family == socket.AF_UNIX: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, None, 0) + + + class HelperFunctionTests(unittest.TestCase): def test_readwriteexc(self): # Check exception handling behavior of read, write and _exception @@ -469,6 +475,7 @@ class BaseServer(asyncore.dispatcher): def __init__(self, family, addr, handler=BaseTestHandler): asyncore.dispatcher.__init__(self) self.create_socket(family) + setsock_no_peercred(self.socket) self.set_reuse_addr() bind_af_aware(self.socket, addr) self.listen(5) @@ -490,6 +497,7 @@ class BaseClient(BaseTestHandler): def __init__(self, family, address): BaseTestHandler.__init__(self) self.create_socket(family) + setsock_no_peercred(self.socket) self.connect(address) def handle_connect(self): @@ -550,6 +558,7 @@ class TestListener(BaseTestHandler): def __init__(self, family, addr): BaseTestHandler.__init__(self) self.create_socket(family) + setsock_no_peercred(self.socket) bind_af_aware(self.socket, addr) self.listen(5) self.address = self.socket.getsockname() From d24bdb9a1876960fb63734e903c23a5343f90635 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 27 Oct 2017 13:29:08 +0200 Subject: [PATCH 2/2] Several other tests that are affected by the Cygwin SO_PEERCRED bug. Unfortunately it's harder to work around in these tests since socket creation is significantly more buried in the code being tested. Better to just skip them. --- Lib/test/test_asyncio/test_events.py | 5 +++++ Lib/test/test_asyncio/test_streams.py | 1 + 2 files changed, 6 insertions(+) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index a6941aa4a60e374..63aaf670bd5b65a 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -471,6 +471,7 @@ def test_sock_client_ops(self): self._basetest_sock_recv_into(httpd, sock) @support.skip_unless_bind_unix_socket + @unittest.skipIf(sys.platform == 'cygwin', 'cygwin has known bug') def test_unix_sock_client_ops(self): with test_utils.run_test_unix_server() as httpd: sock = socket.socket(socket.AF_UNIX) @@ -962,6 +963,7 @@ def _make_unix_server(self, factory, **kwargs): return server, path @support.skip_unless_bind_unix_socket + @unittest.skipIf(sys.platform == 'cygwin', 'cygwin has known bug') def test_create_unix_server(self): proto = MyProto(loop=self.loop) server, path = self._make_unix_server(lambda: proto) @@ -1055,6 +1057,7 @@ def test_create_server_ssl(self): @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') + @unittest.skipIf(sys.platform == 'cygwin', 'cygwin has known bug') def test_create_unix_server_ssl(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( @@ -1115,6 +1118,7 @@ def test_create_server_ssl_verify_failed(self): @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') + @unittest.skipIf(sys.platform == 'cygwin', 'cygwin has known bug') def test_create_unix_server_ssl_verify_failed(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( @@ -1173,6 +1177,7 @@ def test_create_server_ssl_match_failed(self): @support.skip_unless_bind_unix_socket @unittest.skipIf(ssl is None, 'No ssl module') + @unittest.skipIf(sys.platform == 'cygwin', 'cygwin has known bug') def test_create_unix_server_ssl_verified(self): proto = MyProto(loop=self.loop) server, path = self._make_ssl_unix_server( diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index a1e5bd7fab6c8e1..6f705669b75573c 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -636,6 +636,7 @@ def client(addr): self.assertEqual(msg, b"hello world!\n") @support.skip_unless_bind_unix_socket + @unittest.skipIf(sys.platform == 'cygwin', 'cygwin has known bug') def test_start_unix_server(self): class MyServer: