]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46771: Remove two controversial lines from Task.cancel() (GH-31623)
authorGuido van Rossum <guido@python.org>
Mon, 28 Feb 2022 23:15:56 +0000 (15:15 -0800)
committerGitHub <noreply@github.com>
Mon, 28 Feb 2022 23:15:56 +0000 (15:15 -0800)
Also from the _asyncio C accelerator module,
and adjust one test that the change caused to fail.

For more discussion see the discussion starting here:
https://github.com/python/cpython/pull/31394#issuecomment-1053545331

(Basically, @asvetlov proposed to return False from cancel()
when there is already a pending cancellation, and I went along,
even though it wasn't necessary for the task group implementation,
and @agronholm has come up with a counterexample that fails
because of this change.  So now I'm changing it back to the old
semantics (but still bumping the counter) until we can have a
proper discussion about this.)

Lib/asyncio/tasks.py
Lib/test/test_asyncio/test_tasks.py
Modules/_asynciomodule.c

index 38c23851102a8b2404f35631e374e01626449005..059143fb9086fb087089844e8fcd579d76199ed5 100644 (file)
@@ -205,8 +205,11 @@ class Task(futures._PyFuture):  # Inherit Python Task implementation
         if self.done():
             return False
         self._num_cancels_requested += 1
-        if self._num_cancels_requested > 1:
-            return False
+        # These two lines are controversial.  See discussion starting at
+        # https://github.com/python/cpython/pull/31394#issuecomment-1053545331
+        # Also remember that this is duplicated in _asynciomodule.c.
+        # if self._num_cancels_requested > 1:
+        #     return False
         if self._fut_waiter is not None:
             if self._fut_waiter.cancel(msg=msg):
                 # Leave self._fut_waiter; it may be a Task that
index b30f8f56dfa7263820ab89fd68cc51cc2bc7213b..950879204e703b758920c78f195fd8f2eb8e0610 100644 (file)
@@ -514,7 +514,11 @@ class BaseTaskTests:
             self.assertTrue(t.cancel())
             self.assertTrue(t.cancelling())
             self.assertIn(" cancelling ", repr(t))
-            self.assertFalse(t.cancel())
+
+            # Since we commented out two lines from Task.cancel(),
+            # this t.cancel() call now returns True.
+            # self.assertFalse(t.cancel())
+            self.assertTrue(t.cancel())
 
             with self.assertRaises(asyncio.CancelledError):
                 loop.run_until_complete(t)
index 88471239529a55b60432b51afbe5f9ce1f8d5fe3..2a6c0b335ccfb09c6f37a432f9cf938a875a1003 100644 (file)
@@ -2206,9 +2206,13 @@ _asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
     }
 
     self->task_num_cancels_requested += 1;
-    if (self->task_num_cancels_requested > 1) {
-        Py_RETURN_FALSE;
-    }
+
+    // These three lines are controversial.  See discussion starting at
+    // https://github.com/python/cpython/pull/31394#issuecomment-1053545331
+    // and corresponding code in tasks.py.
+    // if (self->task_num_cancels_requested > 1) {
+    //     Py_RETURN_FALSE;
+    // }
 
     if (self->task_fut_waiter) {
         PyObject *res;