File tree Expand file tree Collapse file tree 4 files changed +39
-1
lines changed
Expand file tree Collapse file tree 4 files changed +39
-1
lines changed Original file line number Diff line number Diff line change @@ -180,7 +180,12 @@ def _step(self, exc=None):
180180 else :
181181 result = coro .throw (exc )
182182 except StopIteration as exc :
183- self .set_result (exc .value )
183+ if self ._must_cancel :
184+ # Task is cancelled right before coro stops.
185+ self ._must_cancel = False
186+ self .set_exception (futures .CancelledError ())
187+ else :
188+ self .set_result (exc .value )
184189 except futures .CancelledError :
185190 super ().cancel () # I.e., Future.cancel(self).
186191 except Exception as exc :
Original file line number Diff line number Diff line change @@ -588,6 +588,24 @@ def task():
588588 self .assertFalse (t ._must_cancel ) # White-box test.
589589 self .assertFalse (t .cancel ())
590590
591+ def test_cancel_at_end (self ):
592+ """coroutine end right after task is cancelled"""
593+ loop = asyncio .new_event_loop ()
594+ self .set_event_loop (loop )
595+
596+ @asyncio .coroutine
597+ def task ():
598+ t .cancel ()
599+ self .assertTrue (t ._must_cancel ) # White-box test.
600+ return 12
601+
602+ t = self .new_task (loop , task ())
603+ self .assertRaises (
604+ asyncio .CancelledError , loop .run_until_complete , t )
605+ self .assertTrue (t .done ())
606+ self .assertFalse (t ._must_cancel ) # White-box test.
607+ self .assertFalse (t .cancel ())
608+
591609 def test_stop_while_run_in_complete (self ):
592610
593611 def gen ():
Original file line number Diff line number Diff line change @@ -36,6 +36,9 @@ Core and Builtins
3636Library
3737-------
3838
39+ - bpo-30048: Fixed ``Task.cancel()`` can be ignored when the task is
40+ running coroutine and the coroutine returned without any more ``await``.
41+
3942- bpo-30298: Weaken the condition of deprecation warnings for inline modifiers.
4043 Now allowed several subsequential inline modifiers at the start of the
4144 pattern (e.g. ``'(?i)(?s)...'``). In verbose mode whitespaces and comments
Original file line number Diff line number Diff line change @@ -1984,6 +1984,16 @@ task_step_impl(TaskObj *task, PyObject *exc)
19841984 if (_PyGen_FetchStopIterationValue (& o ) == 0 ) {
19851985 /* The error is StopIteration and that means that
19861986 the underlying coroutine has resolved */
1987+ if (task -> task_must_cancel ) {
1988+ // Task is cancelled right before coro stops.
1989+ Py_DECREF (o );
1990+ task -> task_must_cancel = 0 ;
1991+ et = asyncio_CancelledError ;
1992+ Py_INCREF (et );
1993+ ev = NULL ;
1994+ tb = NULL ;
1995+ goto set_exception ;
1996+ }
19871997 PyObject * res = future_set_result ((FutureObj * )task , o );
19881998 Py_DECREF (o );
19891999 if (res == NULL ) {
@@ -2001,6 +2011,8 @@ task_step_impl(TaskObj *task, PyObject *exc)
20012011
20022012 /* Some other exception; pop it and call Task.set_exception() */
20032013 PyErr_Fetch (& et , & ev , & tb );
2014+
2015+ set_exception :
20042016 assert (et );
20052017 if (!ev || !PyObject_TypeCheck (ev , (PyTypeObject * ) et )) {
20062018 PyErr_NormalizeException (& et , & ev , & tb );
You can’t perform that action at this time.
0 commit comments