Skip to content

Commit

Permalink
pythongh-107219: Fix concurrent.futures terminate_broken()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vstinner committed Sep 6, 2023
1 parent 6f8411c commit 929dea4
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 1 deletion.
9 changes: 8 additions & 1 deletion Lib/concurrent/futures/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,14 @@ def terminate_broken(self, cause):

# 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()
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_concurrent_futures/test_deadlock.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ def test_crash_big_data(self):
with self.assertRaises(BrokenProcessPool):
list(executor.map(_crash_with_data, [data] * 10))

executor.shutdown(wait=True)


create_executor_tests(globals(), ExecutorDeadlockTest,
executor_mixins=(ProcessPoolForkMixin,
Expand Down

0 comments on commit 929dea4

Please sign in to comment.