-
-
Notifications
You must be signed in to change notification settings - Fork 182
locks: Fix inconsistency cancelling Condition.wait. #346
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -457,6 +457,31 @@ def test_wait_cancel(self): | |
| self.assertFalse(cond._waiters) | ||
| self.assertTrue(cond.locked()) | ||
|
|
||
| def test_wait_cancel_contested(self): | ||
| cond = asyncio.Condition(loop=self.loop) | ||
|
|
||
| self.loop.run_until_complete(cond.acquire()) | ||
| self.assertTrue(cond.locked()) | ||
|
|
||
| wait_task = asyncio.Task(cond.wait(), loop=self.loop) | ||
| test_utils.run_briefly(self.loop) | ||
| self.assertFalse(cond.locked()) | ||
|
|
||
| # Notify, but contest the lock before cancelling | ||
| self.loop.run_until_complete(cond.acquire()) | ||
| self.assertTrue(cond.locked()) | ||
| cond.notify() | ||
| self.loop.call_soon(wait_task.cancel) | ||
| self.loop.call_soon(cond.release) | ||
|
|
||
| try: | ||
| self.loop.run_until_complete(wait_task) | ||
| except asyncio.CancelledError: | ||
| # Should not happen, since no cancellation points | ||
| pass | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But why do we have the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason this was just a pass rather than a hard-fail is so that we reach the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should that try-except be replaced with self.assertRaises? Sent from my iPhone
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately you then get the opposite problem where no exception is raised once bug is fixed. Stuck between these two unfortunate alternatives, I decided that using |
||
|
|
||
| self.assertTrue(cond.locked()) | ||
|
|
||
| def test_wait_unacquired(self): | ||
| cond = asyncio.Condition(loop=self.loop) | ||
| self.assertRaises( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally I had a
self.assertRaises(asyncio.CancelledError, ...)here, but since we successfully notified this task before cancellation no exception should be raises. However if the fix is not applied then a CancelledError will be raised so we have to be prepared to handle it so we can check the lock state afterwards.