Description
Bug report
concurrent.futures.wait()
hangs if given a future that is already cancelled.
Steps to reproduce:
- Get a future that is cancellable (create lots of jobs such that the later ones cannot start yet and are therefore cancellable):
>>> import concurrent.futures
>>> pool = concurrent.futures.ThreadPoolExecutor(max_workers=1)
>>> import time
>>> for _ in range(1000): future = pool.submit(time.sleep, 1000)
- Cancel this future and note that it returns
True
meaning it has been cancelled.
>>> future.cancel()
True
- Now waiting on this future hangs:
>>> concurrent.futures.wait([future])
The expected behaviour, regardless of the value of return_when
is that wait()
treats cancelled futures as already completed. This is essentially how return_when=FIRST_COMPLETED
and return_when=ALL_COMPLETED
are documented to behave:
The function will return when any future finishes or is cancelled.
and
The function will return when all futures finish or are cancelled.
Treating a future that is cancelled prior to wait()
as different to one that changes state to cancelled once waiting risks a race condition: it could change state after any possible check but before blocking. i.e. it needs to be level-triggered not edge-triggered. And indeed, it works this way for futures that are done, just not ones that are cancelled.
Your environment
- CPython versions tested on: 3.9.7, 3.10.2
- Operating system and architecture: Linux
Metadata
Metadata
Assignees
Projects
Status