@@ -91,7 +91,7 @@ typedef struct {
9191 PyObject * task_context ;
9292 int task_must_cancel ;
9393 int task_log_destroy_pending ;
94- int task_cancel_requested ;
94+ int task_num_cancels_requested ;
9595} TaskObj ;
9696
9797typedef struct {
@@ -2036,7 +2036,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
20362036 Py_CLEAR (self -> task_fut_waiter );
20372037 self -> task_must_cancel = 0 ;
20382038 self -> task_log_destroy_pending = 1 ;
2039- self -> task_cancel_requested = 0 ;
2039+ self -> task_num_cancels_requested = 0 ;
20402040 Py_INCREF (coro );
20412041 Py_XSETREF (self -> task_coro , coro );
20422042
@@ -2191,22 +2191,24 @@ not return True (unless the task was already cancelled). A
21912191task will be marked as cancelled when the wrapped coroutine
21922192terminates with a CancelledError exception (even if cancel()
21932193was not called).
2194+
2195+ This also increases the task's count of cancellation requests.
21942196[clinic start generated code]*/
21952197
21962198static PyObject *
21972199_asyncio_Task_cancel_impl (TaskObj * self , PyObject * msg )
2198- /*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00 ]*/
2200+ /*[clinic end generated code: output=c66b60d41c74f9f1 input=7bb51bf25974c783 ]*/
21992201{
22002202 self -> task_log_tb = 0 ;
22012203
22022204 if (self -> task_state != STATE_PENDING ) {
22032205 Py_RETURN_FALSE ;
22042206 }
22052207
2206- if (self -> task_cancel_requested ) {
2208+ self -> task_num_cancels_requested += 1 ;
2209+ if (self -> task_num_cancels_requested > 1 ) {
22072210 Py_RETURN_FALSE ;
22082211 }
2209- self -> task_cancel_requested = 1 ;
22102212
22112213 if (self -> task_fut_waiter ) {
22122214 PyObject * res ;
@@ -2238,51 +2240,40 @@ _asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
22382240/*[clinic input]
22392241_asyncio.Task.cancelling
22402242
2241- Return True if the task is in the process of being cancelled.
2242-
2243- This is set once .cancel() is called
2244- and remains set until .uncancel() is called.
2243+ Return the count of the task's cancellation requests.
22452244
2246- As long as this flag is set, further .cancel() calls will be ignored,
2247- until .uncancel() is called to reset it .
2245+ This count is incremented when .cancel() is called
2246+ and may be decremented using .uncancel() .
22482247[clinic start generated code]*/
22492248
22502249static PyObject *
22512250_asyncio_Task_cancelling_impl (TaskObj * self )
2252- /*[clinic end generated code: output=803b3af96f917d7e input=c50e50f9c3ca4676 ]*/
2251+ /*[clinic end generated code: output=803b3af96f917d7e input=b625224d310cbb17 ]*/
22532252/*[clinic end generated code]*/
22542253{
2255- if (self -> task_cancel_requested ) {
2256- Py_RETURN_TRUE ;
2257- }
2258- else {
2259- Py_RETURN_FALSE ;
2260- }
2254+ return PyLong_FromLong (self -> task_num_cancels_requested );
22612255}
22622256
22632257/*[clinic input]
22642258_asyncio.Task.uncancel
22652259
2266- Reset the flag returned by cancelling() .
2260+ Decrement the task's count of cancellation requests .
22672261
22682262This should be used by tasks that catch CancelledError
22692263and wish to continue indefinitely until they are cancelled again.
22702264
2271- Returns the previous value of the flag .
2265+ Returns the remaining number of cancellation requests .
22722266[clinic start generated code]*/
22732267
22742268static PyObject *
22752269_asyncio_Task_uncancel_impl (TaskObj * self )
2276- /*[clinic end generated code: output=58184d236a817d3c input=5db95e28fcb6f7cd ]*/
2270+ /*[clinic end generated code: output=58184d236a817d3c input=68f81a4b90b46be2 ]*/
22772271/*[clinic end generated code]*/
22782272{
2279- if (self -> task_cancel_requested ) {
2280- self -> task_cancel_requested = 0 ;
2281- Py_RETURN_TRUE ;
2282- }
2283- else {
2284- Py_RETURN_FALSE ;
2273+ if (self -> task_num_cancels_requested > 0 ) {
2274+ self -> task_num_cancels_requested -= 1 ;
22852275 }
2276+ return PyLong_FromLong (self -> task_num_cancels_requested );
22862277}
22872278
22882279/*[clinic input]
0 commit comments