From 72783ce1edde73716fc2bf624e3d2284c5b8c95e Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Sat, 1 Mar 2025 09:44:53 -0500 Subject: [PATCH 1/5] gh-128364: Fix flaky `test_timeout` test --- Lib/test/test_concurrent_futures/test_wait.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_concurrent_futures/test_wait.py b/Lib/test/test_concurrent_futures/test_wait.py index 108cf54bf79e6f..4555097174412a 100644 --- a/Lib/test/test_concurrent_futures/test_wait.py +++ b/Lib/test/test_concurrent_futures/test_wait.py @@ -114,9 +114,9 @@ def test_all_completed(self): def test_timeout(self): short_timeout = 0.050 - long_timeout = short_timeout * 10 + event = threading.Event() - future = self.executor.submit(time.sleep, long_timeout) + future = self.executor.submit(event.wait) finished, pending = futures.wait( [CANCELLED_AND_NOTIFIED_FUTURE, @@ -126,6 +126,9 @@ def test_timeout(self): timeout=short_timeout, return_when=futures.ALL_COMPLETED) + event.set() + futures.wait([future], return_when=futures.ALL_COMPLETED) + self.assertEqual(set([CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE, SUCCESSFUL_FUTURE]), From 827bbbbd9f44ad3d06d5e2ffb64d6ee94f2719bd Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Sat, 1 Mar 2025 10:24:23 -0500 Subject: [PATCH 2/5] Use multiprocessing.Manager for process based executors --- Lib/test/test_concurrent_futures/test_wait.py | 6 +++--- Lib/test/test_concurrent_futures/util.py | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_concurrent_futures/test_wait.py b/Lib/test/test_concurrent_futures/test_wait.py index 4555097174412a..e7a3084b1ec30e 100644 --- a/Lib/test/test_concurrent_futures/test_wait.py +++ b/Lib/test/test_concurrent_futures/test_wait.py @@ -114,9 +114,9 @@ def test_all_completed(self): def test_timeout(self): short_timeout = 0.050 - event = threading.Event() + self.event.clear() - future = self.executor.submit(event.wait) + future = self.executor.submit(self.event.wait) finished, pending = futures.wait( [CANCELLED_AND_NOTIFIED_FUTURE, @@ -126,7 +126,7 @@ def test_timeout(self): timeout=short_timeout, return_when=futures.ALL_COMPLETED) - event.set() + self.event.set() futures.wait([future], return_when=futures.ALL_COMPLETED) self.assertEqual(set([CANCELLED_AND_NOTIFIED_FUTURE, diff --git a/Lib/test/test_concurrent_futures/util.py b/Lib/test/test_concurrent_futures/util.py index 44086217f9dbcb..4e9e4ef1daec03 100644 --- a/Lib/test/test_concurrent_futures/util.py +++ b/Lib/test/test_concurrent_futures/util.py @@ -1,5 +1,6 @@ import multiprocessing import sys +import threading import time import unittest from concurrent import futures @@ -46,11 +47,14 @@ def setUp(self): self.t1 = time.monotonic() if hasattr(self, "ctx"): + self.manager = multiprocessing.Manager() + self.event = self.manager.Event() self.executor = self.executor_type( max_workers=self.worker_count, mp_context=self.get_context(), **self.executor_kwargs) else: + self.event = threading.Event() self.executor = self.executor_type( max_workers=self.worker_count, **self.executor_kwargs) @@ -58,6 +62,9 @@ def setUp(self): def tearDown(self): self.executor.shutdown(wait=True) self.executor = None + if hasattr(self, "ctx"): + self.manager.shutdown() + self.manager = None dt = time.monotonic() - self.t1 if support.verbose: From 44483a0a840ba6106732cfba8e9e0079ff069182 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Sat, 1 Mar 2025 10:37:50 -0500 Subject: [PATCH 3/5] Clean up code --- Lib/test/test_concurrent_futures/test_wait.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_concurrent_futures/test_wait.py b/Lib/test/test_concurrent_futures/test_wait.py index e7a3084b1ec30e..6e1724c7360181 100644 --- a/Lib/test/test_concurrent_futures/test_wait.py +++ b/Lib/test/test_concurrent_futures/test_wait.py @@ -126,15 +126,14 @@ def test_timeout(self): timeout=short_timeout, return_when=futures.ALL_COMPLETED) - self.event.set() - futures.wait([future], return_when=futures.ALL_COMPLETED) - self.assertEqual(set([CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE, SUCCESSFUL_FUTURE]), finished) self.assertEqual(set([future]), pending) + # Set the event to allow the future to complete + self.event.set() class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests, BaseTestCase): From adc7436bdbbab5da142aa9ac12e66733861be572 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Sat, 1 Mar 2025 10:42:11 -0500 Subject: [PATCH 4/5] Update Lib/test/test_concurrent_futures/test_wait.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/test/test_concurrent_futures/test_wait.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_concurrent_futures/test_wait.py b/Lib/test/test_concurrent_futures/test_wait.py index 6e1724c7360181..abe9d2ff130557 100644 --- a/Lib/test/test_concurrent_futures/test_wait.py +++ b/Lib/test/test_concurrent_futures/test_wait.py @@ -135,6 +135,7 @@ def test_timeout(self): # Set the event to allow the future to complete self.event.set() + class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests, BaseTestCase): def test_pending_calls_race(self): From 758ca25889d02ecf501c0132eebaa06fd5d957e8 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Sat, 1 Mar 2025 10:55:52 -0500 Subject: [PATCH 5/5] Remove event.clear() call --- Lib/test/test_concurrent_futures/test_wait.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_concurrent_futures/test_wait.py b/Lib/test/test_concurrent_futures/test_wait.py index abe9d2ff130557..697285779510a9 100644 --- a/Lib/test/test_concurrent_futures/test_wait.py +++ b/Lib/test/test_concurrent_futures/test_wait.py @@ -114,7 +114,6 @@ def test_all_completed(self): def test_timeout(self): short_timeout = 0.050 - self.event.clear() future = self.executor.submit(self.event.wait)