bpo-45711: [asyncio] Normalize exceptions immediately after Fetch, before they are stored as StackItem, which should be normalized (GH-29890)

This commit is contained in:
Irit Katriel 2021-12-03 19:05:14 +00:00 committed by GitHub
parent 84ca1232b0
commit 2ff758bd1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 7 deletions

View file

@ -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.

View file

@ -2702,6 +2702,11 @@ task_step_impl(TaskObj *task, PyObject *exc)
if (PyErr_ExceptionMatches(asyncio_CancelledError)) { if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
/* CancelledError */ /* CancelledError */
PyErr_Fetch(&et, &ev, &tb); PyErr_Fetch(&et, &ev, &tb);
assert(et);
PyErr_NormalizeException(&et, &ev, &tb);
if (tb != NULL) {
PyException_SetTraceback(ev, tb);
}
FutureObj *fut = (FutureObj*)task; FutureObj *fut = (FutureObj*)task;
_PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; _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() */ /* Some other exception; pop it and call Task.set_exception() */
PyErr_Fetch(&et, &ev, &tb); PyErr_Fetch(&et, &ev, &tb);
assert(et); assert(et);
if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
PyErr_NormalizeException(&et, &ev, &tb); PyErr_NormalizeException(&et, &ev, &tb);
}
if (tb != NULL) { if (tb != NULL) {
PyException_SetTraceback(ev, tb); PyException_SetTraceback(ev, tb);
} }
o = future_set_exception((FutureObj*)task, ev); o = future_set_exception((FutureObj*)task, ev);
if (!o) { if (!o) {
/* An exception in Task.set_exception() */ /* An exception in Task.set_exception() */
@ -2965,7 +2968,7 @@ task_step(TaskObj *task, PyObject *exc)
PyObject *et, *ev, *tb; PyObject *et, *ev, *tb;
PyErr_Fetch(&et, &ev, &tb); PyErr_Fetch(&et, &ev, &tb);
leave_task(task->task_loop, (PyObject*)task); leave_task(task->task_loop, (PyObject*)task);
_PyErr_ChainExceptions(et, ev, tb); _PyErr_ChainExceptions(et, ev, tb); /* Normalizes (et, ev, tb) */
return NULL; return NULL;
} }
else { else {
@ -3014,8 +3017,10 @@ task_wakeup(TaskObj *task, PyObject *o)
} }
PyErr_Fetch(&et, &ev, &tb); PyErr_Fetch(&et, &ev, &tb);
if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) { assert(et);
PyErr_NormalizeException(&et, &ev, &tb); PyErr_NormalizeException(&et, &ev, &tb);
if (tb != NULL) {
PyException_SetTraceback(ev, tb);
} }
result = task_step(task, ev); result = task_step(task, ev);