Message 413402 - Python tracker (original) (raw)

@Guido @Chris

Instead of using the message for the nonce we could have a dedicated field for it.

I have a proposal though. It's about putting a little logic into the cancellation nonce handling.

Let's define the nonce as a float. If you just call Task.cancel(), the nonce defaults to 0.0. We add an argument to Task.cancel, so you can give it a nonce: task.cancel(nonce=nonce). The cancel() method has logic to keep track of the nonce with the smallest value.

When it's time for the CancelledError to be thrown into the task, this nonce (default 0.0 if not set by anthing) is attached to the error.

Then we change move_on_after (and all siblings) to do the following:

How this fixes the sad path in my example:

Both the web server and move_on_after cancel the task. The web server just calls task.cancel(), move_on_after calls task.cancel(nonce=self.nonce). No matter the cancellation ordering, the nonce will end up set to 0.0. move_on_after will see the 0.0 nonce and propagate the error correctly to kill the task completely.

This also handles nested cancel scopes. I'm not sure how it works with the task catching the cancel to do a little cleanup.