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):
180
180
else :
181
181
result = coro .throw (exc )
182
182
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 )
184
189
except futures .CancelledError :
185
190
super ().cancel () # I.e., Future.cancel(self).
186
191
except Exception as exc :
Original file line number Diff line number Diff line change @@ -588,6 +588,24 @@ def task():
588
588
self .assertFalse (t ._must_cancel ) # White-box test.
589
589
self .assertFalse (t .cancel ())
590
590
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
+
591
609
def test_stop_while_run_in_complete (self ):
592
610
593
611
def gen ():
Original file line number Diff line number Diff line change @@ -36,6 +36,9 @@ Core and Builtins
36
36
Library
37
37
-------
38
38
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
+
39
42
- bpo-30298: Weaken the condition of deprecation warnings for inline modifiers.
40
43
Now allowed several subsequential inline modifiers at the start of the
41
44
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)
1984
1984
if (_PyGen_FetchStopIterationValue (& o ) == 0 ) {
1985
1985
/* The error is StopIteration and that means that
1986
1986
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
+ }
1987
1997
PyObject * res = future_set_result ((FutureObj * )task , o );
1988
1998
Py_DECREF (o );
1989
1999
if (res == NULL ) {
@@ -2001,6 +2011,8 @@ task_step_impl(TaskObj *task, PyObject *exc)
2001
2011
2002
2012
/* Some other exception; pop it and call Task.set_exception() */
2003
2013
PyErr_Fetch (& et , & ev , & tb );
2014
+
2015
+ set_exception :
2004
2016
assert (et );
2005
2017
if (!ev || !PyObject_TypeCheck (ev , (PyTypeObject * ) et )) {
2006
2018
PyErr_NormalizeException (& et , & ev , & tb );
You can’t perform that action at this time.
0 commit comments