diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index be2fc3edf5dce66..ba7f5692785d9be 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -1062,7 +1062,7 @@ def _exhaustive_wait(handles, timeout): return [] ready.extend(L[i] for i in res) if res: - L = [h for i, h in enumerate(L) if i > res[0] & i not in res] + L = [h for i, h in enumerate(L) if i > res[0] and i not in res] timeout = 0 while L: short_L = L[:60] if len(L) > 60 else L diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index e5f618f5f2e84f4..da807b4733cc3cd 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -5918,6 +5918,30 @@ def test_neg_timeout(self): a.close() b.close() + @unittest.skipUnless(WIN32, "skipped on non-Windows platforms") + def test_exhaustive_wait_more_than_60_handles(self): + import _winapi + from multiprocessing.connection import _exhaustive_wait + + # More than 60 handles takes the batched path. Manual reset events + # stay signalled, so the handles the batched wait already reported + # must be dropped from the list that is scanned afterwards. + events = [_winapi.CreateEventW(0, True, False, None) + for _ in range(70)] + self.addCleanup(lambda: [_winapi.CloseHandle(e) for e in events]) + + # BatchedWaitForMultipleObjects reports the lowest signalled handle + # of each 63 handle batch, so signalling the first event pins the + # first reported index at 0 and spreads the rest over both batches. + chosen = [0, 17, 42, 68] + for i in chosen: + _winapi.SetEvent(events[i]) + + # A zero timeout is not usable here: the batched wait would report a + # timeout before its worker threads have run. + ready = _exhaustive_wait(events, 10_000) + self.assertEqual(sorted(ready), sorted(events[i] for i in chosen)) + # # Issue 14151: Test invalid family on invalid environment # diff --git a/Misc/NEWS.d/next/Library/2026-08-19-21-00-25.gh-issue-156070.fwmRPu.rst b/Misc/NEWS.d/next/Library/2026-08-19-21-00-25.gh-issue-156070.fwmRPu.rst new file mode 100644 index 000000000000000..e4e60a0674243f8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-19-21-00-25.gh-issue-156070.fwmRPu.rst @@ -0,0 +1,3 @@ +Fix :func:`multiprocessing.connection.wait` on Windows when waiting on more +than 60 objects: an object that was already ready could be reported more than +once, and other ready objects could be left out of the result.