-
Notifications
You must be signed in to change notification settings - Fork 50
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tasks are still run after being cancelled #33
Comments
Greetings, the behaviour you are observing is expected and it's a limitation of the design. Pebble is designed to keep the IPC overhead minimal offering the same performance of similar solutions ( To ship the jobs to the worker processes, Pebble uses a simple To maximize performance, the When you cancel a scheduled job, three possible scenarios may occur.
As the jobs in your example are very small, you are indeed experiencing the third and last scenario. Due to the concurrent nature of the problem, you will notice a small delay between the moment the job is started by the worker and it is actually canceled. Note that this is known and correctly handled by the If stopping the worker from picking up a canceled job is critical for your application, you can add a simple logic to achieve so. You dedicate a import time
from multiprocessing import Pipe
from pebble import ProcessPool
def callback(future):
if future.canceled():
future.cancel_signal.send('cancel')
def function(canceled):
# check if a cancel signal was delivered
if canceled.poll(timeout=0):
print("Canceled job!")
return
print("You won't see this if canceled")
time.sleep(5)
print("Neither you'll see this")
def main():
futures = []
pool = ProcessPool(max_workers=1)
for _ in range(10):
read, write = Pipe()
future = pool.schedule(function, args=[read])
future.cancel_signal = write
future.add_done_callback(callback)
futures.append(future)
time.sleep(3)
for future in futures[2:]:
future.cancel()
pool.close()
pool.join()
if __name__ == '__main__':
main() Keep in mind that this adds IPC complexity and might cause your application to run out of file descriptors if you schedule lots of jobs to the pool. |
Wow, thank you @noxdafox that's really useful info. Your example actually fails for me with the following error (but I think this is due to the backported
I'll see what I can do to get it working, but you've provided confirmation that this isn't actually a bug, so thanks again! Edit: turns out it's a bug in Python's |
Yes that's a limitation of Python 2 I forgot about, sorry. I don't have a Python 2 dev environment at hand so could not try it. Note that the above trick might not work also on Windows. Python |
Firstly, thank you for such a great library! I'm having great success integrating this, but have come up against one problem: if you cancel a future that is not yet running via
future.cancel()
, it still gets run. 2 things stand out as odd, though:task_done
callback is called when the future is cancelled, as expected. This means it is not called again when the task actually finishes running.Note that I am running this on Python 2.7, using the backported
concurrent.futures
library (https://pypi.org/project/futures/).Here is a minimal reproduction case which I have been using to test:
The output is as follows:
As you can see from the code, we're submitting 10 jobs to the pool, which has only a single worker. Each job waits for 5 seconds before returning. After 2 seconds, we cancel all the jobs which are not running or finished (of which there are 9, as the first job is still sleeping). At this point, all 9
task_done
callbacks are fired as expected.Then, once the first job finishes, we'd expect the program to exit as
pool.join()
should return. Instead, the 9 jobs that were previously cancelled each start to run, one after the other. The timestamps aren't shown in my output above, but this happens very fast—so the jobs are being killed almost immediately after starting. You can see by the incrementingpid
that the worker process is indeed being killed in each case.Is there anything we can do here to work around this, or potentially fix the issue? I'm still quite new to the
concurrent.futures
library, so I may well be doing something wrong!Thank you again for the great work here!
Edit: I've just confirmed that this happens on Python 3 as well, using the standard library
concurrent.futures
module.The text was updated successfully, but these errors were encountered: