https://github.com/python/cpython/commit/8f6b0afd401673c47c15e30947244b0fab4291b2
commit: 8f6b0afd401673c47c15e30947244b0fab4291b2
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: picnixz <10796600+picn...@users.noreply.github.com>
date: 2025-04-08T15:36:52Z
summary:

[3.13] gh-132063: ensure that `ProcessPoolExecutor` does not swallow falsey 
exceptions (GH-132129) (#132275)

gh-132063: ensure that `ProcessPoolExecutor` does not swallow falsey exceptions 
(GH-132129)
(cherry picked from commit 933c6653cba235b3af2250bb19713694b560c367)

Co-authored-by: Duprat <ydup...@gmail.com>

files:
A Misc/NEWS.d/next/Library/2025-04-05-15-05-09.gh-issue-132063.KHnslU.rst
M Lib/concurrent/futures/_base.py
M Lib/concurrent/futures/process.py
M Lib/test/test_concurrent_futures/executor.py

diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py
index 6742a07753c921..7d69a5baead428 100644
--- a/Lib/concurrent/futures/_base.py
+++ b/Lib/concurrent/futures/_base.py
@@ -396,7 +396,7 @@ def done(self):
             return self._state in [CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED]
 
     def __get_result(self):
-        if self._exception:
+        if self._exception is not None:
             try:
                 raise self._exception
             finally:
diff --git a/Lib/concurrent/futures/process.py 
b/Lib/concurrent/futures/process.py
index d73ef716134175..cb0b8be55ecced 100644
--- a/Lib/concurrent/futures/process.py
+++ b/Lib/concurrent/futures/process.py
@@ -440,7 +440,7 @@ def process_result_item(self, result_item):
         work_item = self.pending_work_items.pop(result_item.work_id, None)
         # work_item can be None if another process terminated (see above)
         if work_item is not None:
-            if result_item.exception:
+            if result_item.exception is not None:
                 work_item.future.set_exception(result_item.exception)
             else:
                 work_item.future.set_result(result_item.result)
diff --git a/Lib/test/test_concurrent_futures/executor.py 
b/Lib/test/test_concurrent_futures/executor.py
index 3d1372a6428ec0..7442d3bee52ed8 100644
--- a/Lib/test/test_concurrent_futures/executor.py
+++ b/Lib/test/test_concurrent_futures/executor.py
@@ -23,6 +23,21 @@ def make_dummy_object(_):
     return MyObject()
 
 
+# Used in test_swallows_falsey_exceptions
+def raiser(exception, msg='std'):
+    raise exception(msg)
+
+
+class FalseyBoolException(Exception):
+    def __bool__(self):
+        return False
+
+
+class FalseyLenException(Exception):
+    def __len__(self):
+        return 0
+
+
 class ExecutorTest:
     # Executor.shutdown() and context manager usage is tested by
     # ExecutorShutdownTest.
@@ -132,3 +147,16 @@ def test_free_reference(self):
             for _ in support.sleeping_retry(support.SHORT_TIMEOUT):
                 if wr() is None:
                     break
+
+    def test_swallows_falsey_exceptions(self):
+        # see gh-132063: Prevent exceptions that evaluate as falsey
+        # from being ignored.
+        # Recall: `x` is falsey if `len(x)` returns 0 or `bool(x)` returns 
False.
+
+        msg = 'boolbool'
+        with self.assertRaisesRegex(FalseyBoolException, msg):
+            self.executor.submit(raiser, FalseyBoolException, msg).result()
+
+        msg = 'lenlen'
+        with self.assertRaisesRegex(FalseyLenException, msg):
+            self.executor.submit(raiser, FalseyLenException, msg).result()
diff --git 
a/Misc/NEWS.d/next/Library/2025-04-05-15-05-09.gh-issue-132063.KHnslU.rst 
b/Misc/NEWS.d/next/Library/2025-04-05-15-05-09.gh-issue-132063.KHnslU.rst
new file mode 100644
index 00000000000000..d3761759772d03
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-04-05-15-05-09.gh-issue-132063.KHnslU.rst
@@ -0,0 +1,2 @@
+Prevent exceptions that evaluate as falsey (namely, when their ``__bool__`` 
method returns ``False`` or their ``__len__`` method returns 0)
+from being ignored by :class:`concurrent.futures.ProcessPoolExecutor` and 
:class:`concurrent.futures.ThreadPoolExecutor`.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to