Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
gh-132969: Fix error/hang when shutdown(wait=False) and task exited abnormally#133222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading.Please reload this page.
Conversation
…sk exited abnormallyWhen shutdown is called with wait=False, the executor thread keeps runningeven after the ProcessPoolExecutor's state is reset. The executor then triesto replenish the worker processes pool resulting in an error and a potential hangwhen it comes across a worker that has died. Fixed the issue by having_adjust_process_count() return without doing anything if the ProcessPoolExecutor'sstate has been reset.Added unit tests to validate two scenarios:max_workers < num_tasks (exception)max_workers > num_tasks (exception + hang)
Most changes to Pythonrequire a NEWS entry. Add one using theblurb_it web app or theblurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
… into origin/mainSkip forkserver-dependent test on Windows
python-cla-botbot commentedApr 30, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@hugovk: If this is indeed a blocker for the beta, +1 for me -- it shouldn'tbreak anything. But, as week-old issue that affects 3.12+, I think it's OK to defer it. @itamaro: Did you intend this to block the beta? |
Should have said it here, not only in Discord :) |
Thanks all, it's been looked at and sounds like it can wait, so let's defer it. |
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Misc/NEWS.d/next/Library/2025-04-30-19-32-18.gh-issue-132969.EagQ3G.rst OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
…use @unittest.skipIf annotationto skip test on win32, add some more comments
…s by swiching to "spawn"
Misc/NEWS.d/next/Library/2025-04-30-19-32-18.gh-issue-132969.EagQ3G.rst OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
…t_method is "fork" or ("forkserver" and windows)
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
…ntext() as the mp_context
…wn(wait=False) to prevent resource leak when running CI
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
LGTM |
Thank you@YvesDup for the thorough review of my first PR, much appreciated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I'm not very fond of a long NEWS, especially with the "A combination of ...", but it's the full CHANGELOG, so why not.
# gh-132969: avoid error if shutdown(wait=False) is called and state is reset | ||
# and leaving the executor still running |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
# gh-132969: avoiderror if shutdown(wait=False) is called and state is reset | |
#and leaving the executor still running | |
# gh-132969: avoidleaving the executor running after | |
#calling shutdown(wait=False) and state is reset. |
I think this is what you wanted to say right?
f1 = executor.submit(ProcessPoolShutdownTest._good_task_gh_132969, 1) | ||
f2 = executor.submit(ProcessPoolShutdownTest._failing_task_gh_132969, 2) | ||
f3 = executor.submit(ProcessPoolShutdownTest._good_task_gh_132969, 3) | ||
result:int = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
result:int=0 | |
result=0 |
@@ -0,0 +1 @@ | |||
Prevent the ProcessPoolExecutor executor thread, which remains running when shutdown is called with wait=False, from attempting to adjust the pool's worker processes after the object state has already been reset during shutdown. A combination of conditions, including a worker process having terminated abormally, resulted in an exception and a potential hang when the still-running executor thread attempted to replace dead workers within the pool. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Prevent the ProcessPoolExecutor executor thread, which remains running when shutdown is called with wait=False, from attempting to adjust the pool's worker processes after the object state has already been reset during shutdown. A combination of conditions, including a worker process having terminated abormally, resulted in an exception and a potential hang when the still-running executor thread attempted to replace dead workers within the pool. | |
Prevent the:class:`~concurrent.futures.ProcessPoolExecutor` executor thread, | |
which remains running when:meth:`shutdown(wait=False) | |
<concurrent.future.ProcessPoolExecutor.shutdown>`, from | |
attempting to adjust the pool's worker processes after the object state has already been reset during shutdown. | |
A combination of conditions, including a worker process having terminated abormally, | |
resulted in an exception and a potential hang when the still-running executor thread | |
attempted to replace dead workers within the pool. |
@ogbiggles Would you apply the last suggestions ? |
Uh oh!
There was an error while loading.Please reload this page.
When shutdown is called with wait=False, the executor thread keeps running even after the ProcessPoolExecutor's state is reset. The executor then tries to replenish the worker processes pool resulting in an error and a potential hang when it comes across a worker that has died. Fixed the issue by having _adjust_process_count() return without doing anything if the ProcessPoolExecutor's state has been reset.
Added unit tests to validate two scenarios:
max_workers < num_tasks (exception)
max_workers > num_tasks (exception + hang)
ProcessPoolExecutor
raises exception or hangs the process whenshutdown(wait=False)
and worker throws exception #132969