From 2ff758bd1a144ee712e96ae1db91f476c3b252bb Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 3 Dec 2021 19:05:14 +0000 Subject: bpo-45711: [asyncio] Normalize exceptions immediately after Fetch, before they are stored as StackItem, which should be normalized (GH-29890) --- .../Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst | 1 + Modules/_asynciomodule.c | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst diff --git a/Misc/NEWS.d/next/Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst b/Misc/NEWS.d/next/Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst new file mode 100644 index 0000000..b2b5773 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst @@ -0,0 +1 @@ +Make :mod:`asyncio` normalize exceptions as soon as they are captured with :c:func:`PyErr_Fetch`, and before they are stored as an exc_info triplet. This brings :mod:`asyncio` in line with the rest of the codebase, where an exc_info triplet is always normalized. \ No newline at end of file diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index df6644b..267faac 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2702,6 +2702,11 @@ task_step_impl(TaskObj *task, PyObject *exc) if (PyErr_ExceptionMatches(asyncio_CancelledError)) { /* CancelledError */ PyErr_Fetch(&et, &ev, &tb); + assert(et); + PyErr_NormalizeException(&et, &ev, &tb); + if (tb != NULL) { + PyException_SetTraceback(ev, tb); + } FutureObj *fut = (FutureObj*)task; _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; @@ -2714,14 +2719,12 @@ task_step_impl(TaskObj *task, PyObject *exc) /* Some other exception; pop it and call Task.set_exception() */ PyErr_Fetch(&et, &ev, &tb); - assert(et); - if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) { - PyErr_NormalizeException(&et, &ev, &tb); - } + PyErr_NormalizeException(&et, &ev, &tb); if (tb != NULL) { PyException_SetTraceback(ev, tb); } + o = future_set_exception((FutureObj*)task, ev); if (!o) { /* An exception in Task.set_exception() */ @@ -2965,7 +2968,7 @@ task_step(TaskObj *task, PyObject *exc) PyObject *et, *ev, *tb; PyErr_Fetch(&et, &ev, &tb); leave_task(task->task_loop, (PyObject*)task); - _PyErr_ChainExceptions(et, ev, tb); + _PyErr_ChainExceptions(et, ev, tb); /* Normalizes (et, ev, tb) */ return NULL; } else { @@ -3014,8 +3017,10 @@ task_wakeup(TaskObj *task, PyObject *o) } PyErr_Fetch(&et, &ev, &tb); - if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) { - PyErr_NormalizeException(&et, &ev, &tb); + assert(et); + PyErr_NormalizeException(&et, &ev, &tb); + if (tb != NULL) { + PyException_SetTraceback(ev, tb); } result = task_step(task, ev); -- cgit v0.12