`ProcessPoolExecutor` fails to notify when called with `shutdown(cancel_futures=True)`
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 77.2k
- Forks
- 35.9k
- Métriques de merge des PR
- Métriques de PR en attente
Description
Bug report
Bug description:
I am running a small processor that handles large tasks. When a task encounters an exception I want to store all errors (including other tasks errors) and cancel any other queued work.
However, it seems like the ProcessPoolExecutor's _ExecutorManagerThread does not notify any waiting threads of the future cancelations: making the idiom as_completed hang indefinitely.
Minimal Reproducable Example
import concurrent.futures
import time
def task(n: int) -> int:
if n == 2:
raise Exception("Not gonna do it")
else:
time.sleep(0.1)
return n
def main() -> None:
with concurrent.futures.ProcessPoolExecutor(
max_workers=2,
) as executor:
futures = [executor.submit(task, i) for i in range(1, 16)]
for future in concurrent.futures.as_completed(futures):
try:
result = future.result()
except Exception as e:
print(f"Exception: {e}")
executor.shutdown(wait=False, cancel_futures=True)
continue
print(f"Result: {result}")
# Look for 'CANCELLED' here:
print("Other futures states:", [f._state for f in futures])
if __name__ == "__main__":
main()
Workaround
A workaround is to break after the first future that completed with a failure and do a post hoc gathering of other exceptions of non-cancelled futures.
Suggested Fix
One could replace it with:
for work_id, work_item in self.pending_work_items.items():
canceled = work_item.future.cancel()
if canceled:
work_item.future.set_running_or_notify_cancel()
else:
new_pending_work_items[work_id] = work_item
Similar like:
CPython versions tested on:
3.13
Operating systems tested on:
macOS
Linked PRs
- gh-140021
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez dans Lib/concurrent/futures/process.py autour des lignes 520–522 et reproduisez le blocage avec l’exemple minimal de ProcessPoolExecutor. Comparez le comportement proposé avec PR 134618, puis vérifiez que shutdown(cancel_futures=True) notifie les futures annulés afin que as_completed ne reste pas bloqué.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- python
- Domaine
- backend
- Type d'issue
- Bug
- Difficulté
- 3/5
- Temps estimé
- 1-2 jours
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 38/100