From fdb8dcf675427dc1ed710c8e1165cc6f87655a2c Mon Sep 17 00:00:00 2001 From: Richard Oudkerk Date: Sat, 5 May 2012 19:45:37 +0100 Subject: [PATCH] Fix for Issue 14725 for 3.3 branch. --- Lib/multiprocessing/connection.py | 26 +++++++++++++++++--------- Lib/test/test_multiprocessing.py | 16 ++++++++++++++++ Modules/_winapi.c | 4 +--- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index 046a7fc6009..acf43b1feff 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -621,16 +621,24 @@ if sys.platform == 'win32': def accept(self): self._handle_queue.append(self._new_handle()) handle = self._handle_queue.pop(0) - ov = _winapi.ConnectNamedPipe(handle, overlapped=True) try: - res = _winapi.WaitForMultipleObjects([ov.event], False, INFINITE) - except: - ov.cancel() - _winapi.CloseHandle(handle) - raise - finally: - _, err = ov.GetOverlappedResult(True) - assert err == 0 + ov = _winapi.ConnectNamedPipe(handle, overlapped=True) + except OSError as e: + if e.winerror != _winapi.ERROR_NO_DATA: + raise + # ERROR_NO_DATA can occur if a client has already connected, + # written data and then disconnected -- see Issue 14725. + else: + try: + res = _winapi.WaitForMultipleObjects( + [ov.event], False, INFINITE) + except: + ov.cancel() + _winapi.CloseHandle(handle) + raise + finally: + _, err = ov.GetOverlappedResult(True) + assert err == 0 return PipeConnection(handle) @staticmethod diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index 4aa0ba8e1b8..5e471f16135 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -1878,6 +1878,22 @@ class _TestListenerClient(BaseTestCase): p.join() l.close() + def test_issue14725(self): + l = self.connection.Listener() + p = self.Process(target=self._test, args=(l.address,)) + p.daemon = True + p.start() + time.sleep(1) + # On Windows the client process should by now have connected, + # written data and closed the pipe handle by now. This causes + # ConnectNamdedPipe() to fail with ERROR_NO_DATA. See Issue + # 14725. + conn = l.accept() + self.assertEqual(conn.recv(), 'hello') + conn.close() + p.join() + l.close() + class _TestPoll(unittest.TestCase): ALLOWED_TYPES = ('processes', 'threads') diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 6c99394b09f..af6b5d7e098 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -1287,11 +1287,9 @@ PyInit__winapi(void) WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA); WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); - WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); - WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); - WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA); WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); + WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA); WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED); WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);