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 @@ -176,7 +176,12 @@ def _step(self, exc=None):
176176 else :
177177 result = coro .throw (exc )
178178 except StopIteration as exc :
179- self .set_result (exc .value )
179+ if self ._must_cancel :
180+ # Task is cancelled right before coro stops.
181+ self ._must_cancel = False
182+ self .set_exception (futures .CancelledError ())
183+ else :
184+ self .set_result (exc .value )
180185 except futures .CancelledError :
181186 super ().cancel () # I.e., Future.cancel(self).
182187 except Exception as exc :
Original file line number Diff line number Diff line change @@ -587,6 +587,24 @@ def task():
587587 self .assertFalse (t ._must_cancel ) # White-box test.
588588 self .assertFalse (t .cancel ())
589589
590+ def test_cancel_at_end (self ):
591+ """coroutine end right after task is cancelled"""
592+ loop = asyncio .new_event_loop ()
593+ self .set_event_loop (loop )
594+
595+ @asyncio .coroutine
596+ def task ():
597+ t .cancel ()
598+ self .assertTrue (t ._must_cancel ) # White-box test.
599+ return 12
600+
601+ t = self .new_task (loop , task ())
602+ self .assertRaises (
603+ asyncio .CancelledError , loop .run_until_complete , t )
604+ self .assertTrue (t .done ())
605+ self .assertFalse (t ._must_cancel ) # White-box test.
606+ self .assertFalse (t .cancel ())
607+
590608 def test_stop_while_run_in_complete (self ):
591609
592610 def gen ():
Original file line number Diff line number Diff line change @@ -320,6 +320,9 @@ Extension Modules
320320Library
321321-------
322322
323+ - bpo-30048: Fixed ``Task.cancel()`` can be ignored when the task is
324+ running coroutine and the coroutine returned without any more ``await``.
325+
323326- bpo-30298: Weaken the condition of deprecation warnings for inline modifiers.
324327 Now allowed several subsequential inline modifiers at the start of the
325328 pattern (e.g. ``'(?i)(?s)...'``). In verbose mode whitespaces and comments
Original file line number Diff line number Diff line change @@ -1985,6 +1985,16 @@ task_step_impl(TaskObj *task, PyObject *exc)
19851985 if (_PyGen_FetchStopIterationValue (& o ) == 0 ) {
19861986 /* The error is StopIteration and that means that
19871987 the underlying coroutine has resolved */
1988+ if (task -> task_must_cancel ) {
1989+ // Task is cancelled right before coro stops.
1990+ Py_DECREF (o );
1991+ task -> task_must_cancel = 0 ;
1992+ et = asyncio_CancelledError ;
1993+ Py_INCREF (et );
1994+ ev = NULL ;
1995+ tb = NULL ;
1996+ goto set_exception ;
1997+ }
19881998 PyObject * res = future_set_result ((FutureObj * )task , o );
19891999 Py_DECREF (o );
19902000 if (res == NULL ) {
@@ -2002,6 +2012,8 @@ task_step_impl(TaskObj *task, PyObject *exc)
20022012
20032013 /* Some other exception; pop it and call Task.set_exception() */
20042014 PyErr_Fetch (& et , & ev , & tb );
2015+
2016+ set_exception :
20052017 assert (et );
20062018 if (!ev || !PyObject_TypeCheck (ev , (PyTypeObject * ) et )) {
20072019 PyErr_NormalizeException (& et , & ev , & tb );
You can’t perform that action at this time.
0 commit comments