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):
176
176
else :
177
177
result = coro .throw (exc )
178
178
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 )
180
185
except futures .CancelledError :
181
186
super ().cancel () # I.e., Future.cancel(self).
182
187
except Exception as exc :
Original file line number Diff line number Diff line change @@ -587,6 +587,24 @@ def task():
587
587
self .assertFalse (t ._must_cancel ) # White-box test.
588
588
self .assertFalse (t .cancel ())
589
589
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
+
590
608
def test_stop_while_run_in_complete (self ):
591
609
592
610
def gen ():
Original file line number Diff line number Diff line change @@ -320,6 +320,9 @@ Extension Modules
320
320
Library
321
321
-------
322
322
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
+
323
326
- bpo-30298: Weaken the condition of deprecation warnings for inline modifiers.
324
327
Now allowed several subsequential inline modifiers at the start of the
325
328
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)
1985
1985
if (_PyGen_FetchStopIterationValue (& o ) == 0 ) {
1986
1986
/* The error is StopIteration and that means that
1987
1987
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
+ }
1988
1998
PyObject * res = future_set_result ((FutureObj * )task , o );
1989
1999
Py_DECREF (o );
1990
2000
if (res == NULL ) {
@@ -2002,6 +2012,8 @@ task_step_impl(TaskObj *task, PyObject *exc)
2002
2012
2003
2013
/* Some other exception; pop it and call Task.set_exception() */
2004
2014
PyErr_Fetch (& et , & ev , & tb );
2015
+
2016
+ set_exception :
2005
2017
assert (et );
2006
2018
if (!ev || !PyObject_TypeCheck (ev , (PyTypeObject * ) et )) {
2007
2019
PyErr_NormalizeException (& et , & ev , & tb );
You can’t perform that action at this time.
0 commit comments