Author twisteroid ambassador
Recipients Martin.Teichmann, twisteroid ambassador
Date 2018-05-08.08:25:08
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1525767909.87.0.682650639539.issue33413@psf.upfronthosting.co.za>
In-reply-to
Content
I would like to comment on the last observation about current_task().cancel(). I also ran into this corner case recently. 

When a task is cancelled from outside, by virtue of there *being something outside doing the cancelling*, the task being cancelled is not currently running, and that usually means the task is waiting at an `await` statement, in which case a CancelledError will be raised at this `await` statement the next time this task runs. The other possibility is that the task has been created but has not had a chance to run yet, and in this case the task is marked cancelled, and code inside the task will not run.

When one cancels a task from the inside by calling cancel() on the task object, the task will still run as normal until it reaches the next `await` statement, where a CancelledError will be raised. If there is no `await` between calling cancel() and the task returning, however, the CancelledError is never raised inside the task, and the task will end up in the state of done() == True, cancelled() == False, exception() == CancelledError. Anyone awaiting for the task will get a CancelledError without a meaningful stack trace, like this:

Traceback (most recent call last):
  File "cancel_self.py", line 89, in run_one
    loop.run_until_complete(coro)
  File "C:\Program Files\Python36\lib\asyncio\base_events.py", line 467, in run_until_complete
    return future.result()
concurrent.futures._base.CancelledError

This is the case described in the original comment.

I would also consider this a bug or at least undesired behavior. Since CancelledError is never raised inside the task, code in the coroutine cannot catch it, and after the task returns the return value is lost. For a coroutine that acquires and returns some resource (say asyncio.open_connection()), this means that neither the task itself nor the code awaiting the task can release the resource, leading to leakage.

I guess one should be careful not to cancel the current task from the inside.
History
Date User Action Args
2018-05-08 08:25:09twisteroid ambassadorsetrecipients: + twisteroid ambassador, Martin.Teichmann
2018-05-08 08:25:09twisteroid ambassadorsetmessageid: <1525767909.87.0.682650639539.issue33413@psf.upfronthosting.co.za>
2018-05-08 08:25:09twisteroid ambassadorlinkissue33413 messages
2018-05-08 08:25:08twisteroid ambassadorcreate