mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
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:
parent
22b25d1eba
commit
fa58e75a86
8 changed files with 183 additions and 13 deletions
|
@ -392,6 +392,27 @@ is also included in the exception group.
|
|||
The same special case is made for
|
||||
:exc:`KeyboardInterrupt` and :exc:`SystemExit` as in the previous paragraph.
|
||||
|
||||
Task groups are careful not to mix up the internal cancellation used to
|
||||
"wake up" their :meth:`~object.__aexit__` with cancellation requests
|
||||
for the task in which they are running made by other parties.
|
||||
In particular, when one task group is syntactically nested in another,
|
||||
and both experience an exception in one of their child tasks simultaneously,
|
||||
the inner task group will process its exceptions, and then the outer task group
|
||||
will receive another cancellation and process its own exceptions.
|
||||
|
||||
In the case where a task group is cancelled externally and also must
|
||||
raise an :exc:`ExceptionGroup`, it will call the parent task's
|
||||
:meth:`~asyncio.Task.cancel` method. This ensures that a
|
||||
:exc:`asyncio.CancelledError` will be raised at the next
|
||||
:keyword:`await`, so the cancellation is not lost.
|
||||
|
||||
Task groups preserve the cancellation count
|
||||
reported by :meth:`asyncio.Task.cancelling`.
|
||||
|
||||
.. versionchanged:: 3.13
|
||||
|
||||
Improved handling of simultaneous internal and external cancellations
|
||||
and correct preservation of cancellation counts.
|
||||
|
||||
Sleeping
|
||||
========
|
||||
|
@ -1369,6 +1390,15 @@ Task Object
|
|||
catching :exc:`CancelledError`, it needs to call this method to remove
|
||||
the cancellation state.
|
||||
|
||||
When this method decrements the cancellation count to zero,
|
||||
the method checks if a previous :meth:`cancel` call had arranged
|
||||
for :exc:`CancelledError` to be thrown into the task.
|
||||
If it hasn't been thrown yet, that arrangement will be
|
||||
rescinded (by resetting the internal ``_must_cancel`` flag).
|
||||
|
||||
.. versionchanged:: 3.13
|
||||
Changed to rescind pending cancellation requests upon reaching zero.
|
||||
|
||||
.. method:: cancelling()
|
||||
|
||||
Return the number of pending cancellation requests to this Task, i.e.,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue