You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Dec 21, 2025. It is now read-only.
Repository navigation
This repository was archived by the owner on Dec 21, 2025. It is now read-only.
Need a way to protect a region from cancellation (like "masking interrupts") #96
The tricky part is managing these tasks. Basically with regards to exceptions/timeouts/cancellation/etc., we want it to act like the two copy_all tasks are both "part of" the copy_all_bidir task. So:
If one of the tasks raises an exception, the other task should immediately be canceled, and the exception should propagate out of copy_all_bidir
If both of the tasks complete, then copy_all_bidir should complete successfully
If copy_all_bidir is cancelled, then both tasks should be canceled as part of copy_all_bidir's cleanup
The all_or_none helper there tries to do this, but AFAICT it can't quite achieve the last requirement given curio's current APIs. The problem sequence is:
One of the tasks raises an exception
all_or_none catches this exception, and starts to cancel the other task
all_or_none itself gets canceled, thus canceling the cancellation and making everyone's head explode (and also leaking the other task)
In general this is a problem for cleanup code -- once you're executing the cancellation cleanup path you really don't want to get canceled again!
Oh also, this should probably replace the current curio.timeout_after(None) thing. I.e., defer_cancellation should protect against both timeouts and explicit calls to Task.cancel(), and then timeout_after(None) becomes unnecessary.
And the exact semantics I'm proposing are that if a cancellation arrives while defer_cancellation is in effect, then the cancellation exception gets raised from defer_cancellation.__aexit__.
MMmmmmaybe we would also want to make it so that cancellations are automatically deferred when we're in the span between when a timeout fires, and when the timeout exception propagates out to the enclosing timeout block (and gets converted into a different exception). The theory would be that firing a cancellation while we're in the middle of handling a cancellation is not helpful -- same logic that says that calling Task.cancel twice shouldn't fire two cancellation exceptions.
Activity
njsmith commentedon Nov 9, 2016
Oh also, this should probably replace the current
curio.timeout_after(None)thing. I.e.,defer_cancellationshould protect against both timeouts and explicit calls toTask.cancel(), and thentimeout_after(None)becomes unnecessary.And the exact semantics I'm proposing are that if a cancellation arrives while
defer_cancellationis in effect, then the cancellation exception gets raised fromdefer_cancellation.__aexit__.Prior art:
asyncio.shieldnjsmith commentedon Nov 9, 2016
MMmmmmaybe we would also want to make it so that cancellations are automatically deferred when we're in the span between when a timeout fires, and when the timeout exception propagates out to the enclosing timeout block (and gets converted into a different exception). The theory would be that firing a cancellation while we're in the middle of handling a cancellation is not helpful -- same logic that says that calling
Task.canceltwice shouldn't fire two cancellation exceptions.Add curio.defer_cancellation and Task.cancel_no_wait
njsmith commentedon Nov 20, 2016
This was fixed by #99, so closing.