gh-116720: Fix corner cases of taskgroups (#117407)

This prevents external cancellations of a task group's parent task to
be dropped when an internal cancellation happens at the same time.
Also strengthen the semantics of uncancel() to clear self._must_cancel
when the cancellation count reaches zero.

Co-Authored-By: Tin Tvrtković <tinchester@gmail.com>
Co-Authored-By: Arthur Tacca
This commit is contained in:
Guido van Rossum 2024-04-09 08:17:28 -07:00 committed by GitHub
parent 22b25d1eba
commit fa58e75a86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 183 additions and 13 deletions

View file

@ -684,6 +684,30 @@ class BaseTaskTests:
finally:
loop.close()
def test_uncancel_resets_must_cancel(self):
async def coro():
await fut
return 42
loop = asyncio.new_event_loop()
fut = asyncio.Future(loop=loop)
task = self.new_task(loop, coro())
loop.run_until_complete(asyncio.sleep(0)) # Get task waiting for fut
fut.set_result(None) # Make task runnable
try:
task.cancel() # Enter cancelled state
self.assertEqual(task.cancelling(), 1)
self.assertTrue(task._must_cancel)
task.uncancel() # Undo cancellation
self.assertEqual(task.cancelling(), 0)
self.assertFalse(task._must_cancel)
finally:
res = loop.run_until_complete(task)
self.assertEqual(res, 42)
loop.close()
def test_cancel(self):
def gen():