summaryrefslogtreecommitdiffstats
path: root/Doc
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2024-04-09 15:17:28 (GMT)
committerGitHub <noreply@github.com>2024-04-09 15:17:28 (GMT)
commitfa58e75a8605146a89ef72b58b4529669ac48366 (patch)
tree1e15a0af9593b52529a6e637703ea878d6d295e0 /Doc
parent22b25d1ebaab7b8c4833a8c120c8b4699a830f40 (diff)
downloadcpython-fa58e75a8605146a89ef72b58b4529669ac48366.zip
cpython-fa58e75a8605146a89ef72b58b4529669ac48366.tar.gz
cpython-fa58e75a8605146a89ef72b58b4529669ac48366.tar.bz2
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
Diffstat (limited to 'Doc')
-rw-r--r--Doc/library/asyncio-task.rst30
-rw-r--r--Doc/whatsnew/3.13.rst34
2 files changed, 57 insertions, 7 deletions
diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst
index 3b10a0d..3d300c3 100644
--- a/Doc/library/asyncio-task.rst
+++ b/Doc/library/asyncio-task.rst
@@ -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.,
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 707dcaa..d971beb 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -196,13 +196,6 @@ Other Language Changes
(Contributed by Sebastian Pipping in :gh:`115623`.)
-* When :func:`asyncio.TaskGroup.create_task` is called on an inactive
- :class:`asyncio.TaskGroup`, the given coroutine will be closed (which
- prevents a :exc:`RuntimeWarning` about the given coroutine being
- never awaited).
-
- (Contributed by Arthur Tacca and Jason Zhang in :gh:`115957`.)
-
* The :func:`ssl.create_default_context` API now includes
:data:`ssl.VERIFY_X509_PARTIAL_CHAIN` and :data:`ssl.VERIFY_X509_STRICT`
in its default flags.
@@ -300,6 +293,33 @@ asyncio
with the tasks being completed.
(Contributed by Justin Arthur in :gh:`77714`.)
+* When :func:`asyncio.TaskGroup.create_task` is called on an inactive
+ :class:`asyncio.TaskGroup`, the given coroutine will be closed (which
+ prevents a :exc:`RuntimeWarning` about the given coroutine being
+ never awaited).
+ (Contributed by Arthur Tacca and Jason Zhang in :gh:`115957`.)
+
+* Improved behavior of :class:`asyncio.TaskGroup` when an external cancellation
+ collides with an internal cancellation. For example, when two task groups
+ are nested and both experience an exception in a child task simultaneously,
+ it was possible that the outer task group would hang, because its internal
+ cancellation was swallowed by the inner task group.
+
+ In the case where a task group is cancelled externally and also must
+ raise an :exc:`ExceptionGroup`, it will now 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.
+
+ An added benefit of these changes is that task groups now preserve the
+ cancellation count (:meth:`asyncio.Task.cancelling`).
+
+ In order to handle some corner cases, :meth:`asyncio.Task.uncancel` may now
+ reset the undocumented ``_must_cancel`` flag when the cancellation count
+ reaches zero.
+
+ (Inspired by an issue reported by Arthur Tacca in :gh:`116720`.)
+
* Add :meth:`asyncio.Queue.shutdown` (along with
:exc:`asyncio.QueueShutDown`) for queue termination.
(Contributed by Laurie Opperman and Yves Duprat in :gh:`104228`.)