diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 38c23851102a8b..059143fb9086fb 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -205,8 +205,11 @@ def cancel(self, msg=None): 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 diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index b30f8f56dfa726..950879204e703b 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -514,7 +514,11 @@ async def task(): 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) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 88471239529a55..2a6c0b335ccfb0 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -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;