-
-
Notifications
You must be signed in to change notification settings - Fork 346
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
Delay deciding which cancel scope a Cancelled exception belongs to #860
Comments
I just posted #900 which offers a less elegant, but also less invasive, solution to this problem. I prefer the solution in this issue on aesthetic grounds but I couldn't convince myself that it would be safe in the presence of a cancellation landscape that might be changing as the |
OK, let's try doing this analysis semi-rigorously. I'm interpreting "outermost unshielded scope that's in the cancelled state" here as "the thing that
Looking from the perspective of a single
I think my conclusion here is that I was being overly conservative, this will work fine, and we can drop #900. But I'd like another set of eyes on it before being quite sure. :-) |
Good question, yeah. Right now, at the moment when we inject the In this proposal, each time the exception passes through a cancel scope, we look at a single consistent snapshot of the whole stack, and determine whether the current scope is the outermost-unshielded-cancelled-scope. (So the naive implementation is O(stack depth * number of scopes in the cancel-requested state), which is probably much better than O(stack depth * stack depth), and I think this could be optimized further.) Now, if we discover that this is the outermost-unshielded-cancelled-scope, and catch the exception, then that's definitely OK, because it was the right thing to do at the moment we did it, and then there's nothing afterwards that could go wrong. The riskier case is when we decide not to catch the exception. We know that at the moment we made the decision, there was some outer scope that was a better candidate for catching it. But, what it won't actually be caught until later. Could something happen between now and then that would mess things up? In particular, the thing that would be bad is if we got into a state where there was a live To be a candidate, a scope has to meet two criteria:
Once a scope is in the cancel-requested state, it can never leave it. So if we identified a scope as being a candidate at time T1, then for all times T2 > T1 it is definitely still in the cancel-requested state. But what about the second criterion? It could certainly happen that our original candidate stops fulfilling that – while our Therefore, if in a snapshot at time T1 we decide that our exception has an outer candidate, then we are guaranteed that it will eventually be caught at time T2, even if it's by a different scope than the one we originally thought. Ah, and I see you've just posted osmething too! I will read it. |
OK looks like we made pretty much the same argument :-) |
Put another way, if a cancel scope does interpret a Cancelled exception as being "for us", we can assume that determination is correct (as a matter of definition - the mapping from cancel stacks to "which scope is cancelled here right now" defines the cancellation semantics, we're just following it). So the only real correctness concern is that everyone could conclude "not mine!" and let a |
Great, I'm sufficiently convinced now and will close #900 and work on this instead. :-) |
Running the testsuite with the new behavior exposed a corner case I wasn't expecting, though I don't think it's actually harmful. If you have multiple tasks that are sleeping until the same time using |
Oh yeah, this will definitely change behavior in some edge cases. And some of our low-level tests are very reliant on edge cases, or even checking for them explicitly, so they'll need a bit of tweaking for sure... |
Right now, whenever we create a
Cancelled
exception, we immediately tag it with the cancel scope that's going to catch it.There's another option that's briefly mentioned in #606: we could wait until
CancelScope.__exit__
to decide whether a givenCancelled
exception "belongs" to this scope. The check would be "on the current task's stack, am I the outermost unshielded scope that's in the cancelled state?"This can behave differently from what we have now in cases where there are multiple cancelled
CancelScope
s on the stack.I'm not entirely sure if this would actually help with #606, because of complications noted there (hello
KeyboardInterrupt
). But it would probably simplify the cancel scope code in general, in particular_cancel_no_notify
, and the issues described in this comment: #835 (comment)The text was updated successfully, but these errors were encountered: