diff options
author | Elvis Pranskevichus <elvis@magic.io> | 2018-10-03 14:30:31 (GMT) |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2018-10-03 14:30:31 (GMT) |
commit | 0c797a6aca1c293e530e18c5e9fa02c670a9a4ed (patch) | |
tree | 0a7627593801b009925f9909715b8cacabf6c91e /Modules | |
parent | 96c593279400693226d5a560c420ae0fcf1731b9 (diff) | |
download | cpython-0c797a6aca1c293e530e18c5e9fa02c670a9a4ed.zip cpython-0c797a6aca1c293e530e18c5e9fa02c670a9a4ed.tar.gz cpython-0c797a6aca1c293e530e18c5e9fa02c670a9a4ed.tar.bz2 |
bpo-34872: Fix self-cancellation in C implementation of asyncio.Task (GH-9679)
The C implementation of asyncio.Task currently fails to perform the
cancellation cleanup correctly in the following scenario.
async def task1():
async def task2():
await task3 # task3 is never cancelled
asyncio.current_task().cancel()
await asyncio.create_task(task2())
The actuall error is a hardcoded call to `future_cancel()` instead of
calling the `cancel()` method of a future-like object.
Thanks to Vladimir Matveev for noticing the code discrepancy and to
Yury Selivanov for coming up with a pathological scenario.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_asynciomodule.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 6bf0fd6..eb503fb 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2713,14 +2713,19 @@ set_exception: if (task->task_must_cancel) { PyObject *r; - r = future_cancel(fut); + int is_true; + r = _PyObject_CallMethodId(fut, &PyId_cancel, NULL); if (r == NULL) { return NULL; } - if (r == Py_True) { + is_true = PyObject_IsTrue(r); + Py_DECREF(r); + if (is_true < 0) { + return NULL; + } + else if (is_true) { task->task_must_cancel = 0; } - Py_DECREF(r); } Py_RETURN_NONE; |