-
-
Notifications
You must be signed in to change notification settings - Fork 342
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
Always force tasks off the queue #553
Conversation
When queue.get() is cancelled, the task must not be left on the queue. Otherwise an interesting crash will result when the next item is pushed.
Codecov Report
@@ Coverage Diff @@
## master #553 +/- ##
==========================================
+ Coverage 99.28% 99.28% +<.01%
==========================================
Files 89 89
Lines 10491 10498 +7
Branches 728 728
==========================================
+ Hits 10416 10423 +7
Misses 58 58
Partials 17 17
Continue to review full report at Codecov.
|
@smurfix Ouch, sorry this made you waste time :( Thanks for adding a test and providing a fix! I'm late for review but I want to add a note: I think that cleanup line pertains in the abort function, rather than in a finally clause. The abort function is only called on cancellation, while the finally clause is in the success path. And hopefully |
Umm, no, the |
@smurfix I meant that the What I suggest is: def abort_fn(_):
self._get_wait.pop(task, None)
return _core.Abort.SUCCEEDED
value = await _core.wait_task_rescheduled(abort_fn) |
OK, thanks for clarifying. I didn't do that on purpose because there may be other exceptions (KeyboardInterrupt, anybody?) which would trigger the same problem. |
My point was stronger than that. No other exceptions may occur in a sane state :) KeyboardInterrupt cannot happen in that code, |
@smurfix I see that @pquentin already reminded you about the don't-merge-your-own-PR guideline in chat. No harm done, but just want to mention it here too in case others watching get confused. As you can see, even a small and fundamentally correct fix like this still can have some fiddly bits to get right... @sorcio is correct that Note also that Also, in the test, that 0.01 second timeout is making me itch. I think it does deterministically work right now, but the only reason there's no race condition is because of some subtle details about how the body of async def test_553(autojump_clock):
q = trio.Queue()
with trio.move_on_after(10) as timeout_scope:
await q.get()
assert timeout_scope.cancelled_caught
await q.put("Test for PR #553") |
Apparently not:
|
When queue.get() is cancelled, the task must not be left on the queue.
Otherwise an interesting crash will result when the next item is pushed.
Best demonstrated by: