]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-107219: Fix concurrent.futures terminate_broken() (#108974)
authorVictor Stinner <vstinner@python.org>
Wed, 6 Sep 2023 13:57:01 +0000 (15:57 +0200)
committerGitHub <noreply@github.com>
Wed, 6 Sep 2023 13:57:01 +0000 (15:57 +0200)
Fix a race condition in _ExecutorManagerThread.terminate_broken():
ignore the InvalidStateError on future.set_exception(). It can happen
if the future is cancelled before the caller.

Moreover, test_crash_big_data() now waits explicitly until the
executor completes.

Lib/concurrent/futures/process.py
Lib/test/test_concurrent_futures/test_deadlock.py

index 301207f59de37a5e312de93765268883d7401b20..9933d3d0e040ea0ec76e4274f374e0e263794014 100644 (file)
@@ -489,7 +489,14 @@ class _ExecutorManagerThread(threading.Thread):
 
         # Mark pending tasks as failed.
         for work_id, work_item in self.pending_work_items.items():
-            work_item.future.set_exception(bpe)
+            try:
+                work_item.future.set_exception(bpe)
+            except _base.InvalidStateError as exc:
+                # set_exception() fails if the future is cancelled: ignore it.
+                # Trying to check if the future is cancelled before calling
+                # set_exception() would leave a race condition if the future is
+                # cancelled betwen the check and set_exception().
+                pass
             # Delete references to object. See issue16284
             del work_item
         self.pending_work_items.clear()
index 6b78b360d156275316bc5e76b1cb13369b503a85..baac2b51e0d4e228ac914c3fa3e6a0ea33796cd5 100644 (file)
@@ -239,6 +239,8 @@ class ExecutorDeadlockTest:
             with self.assertRaises(BrokenProcessPool):
                 list(executor.map(_crash_with_data, [data] * 10))
 
+        executor.shutdown(wait=True)
+
 
 create_executor_tests(globals(), ExecutorDeadlockTest,
                       executor_mixins=(ProcessPoolForkMixin,