Skip to content

Commit 2db23d1

Browse files
authored
gh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (in Modules/) (#102196)
1 parent 568fc0d commit 2db23d1

18 files changed

+136
-169
lines changed

Modules/_asynciomodule.c

+22-47
Original file line numberDiff line numberDiff line change
@@ -1422,7 +1422,6 @@ _asyncio_Future__make_cancelled_error_impl(FutureObj *self)
14221422
static void
14231423
FutureObj_finalize(FutureObj *fut)
14241424
{
1425-
PyObject *error_type, *error_value, *error_traceback;
14261425
PyObject *context;
14271426
PyObject *message = NULL;
14281427
PyObject *func;
@@ -1434,7 +1433,7 @@ FutureObj_finalize(FutureObj *fut)
14341433
fut->fut_log_tb = 0;
14351434

14361435
/* Save the current exception, if any. */
1437-
PyErr_Fetch(&error_type, &error_value, &error_traceback);
1436+
PyObject *exc = PyErr_GetRaisedException();
14381437

14391438
context = PyDict_New();
14401439
if (context == NULL) {
@@ -1476,7 +1475,7 @@ FutureObj_finalize(FutureObj *fut)
14761475
Py_XDECREF(message);
14771476

14781477
/* Restore the saved exception. */
1479-
PyErr_Restore(error_type, error_value, error_traceback);
1478+
PyErr_SetRaisedException(exc);
14801479
}
14811480

14821481
static PyMethodDef FutureType_methods[] = {
@@ -2491,14 +2490,13 @@ TaskObj_finalize(TaskObj *task)
24912490
PyObject *context;
24922491
PyObject *message = NULL;
24932492
PyObject *func;
2494-
PyObject *error_type, *error_value, *error_traceback;
24952493

24962494
if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
24972495
goto done;
24982496
}
24992497

25002498
/* Save the current exception, if any. */
2501-
PyErr_Fetch(&error_type, &error_value, &error_traceback);
2499+
PyObject *exc = PyErr_GetRaisedException();
25022500

25032501
context = PyDict_New();
25042502
if (context == NULL) {
@@ -2541,7 +2539,7 @@ TaskObj_finalize(TaskObj *task)
25412539
Py_XDECREF(message);
25422540

25432541
/* Restore the saved exception. */
2544-
PyErr_Restore(error_type, error_value, error_traceback);
2542+
PyErr_SetRaisedException(exc);
25452543

25462544
done:
25472545
FutureObj_finalize((FutureObj*)task);
@@ -2766,8 +2764,6 @@ task_step_impl(asyncio_state *state, TaskObj *task, PyObject *exc)
27662764
}
27672765

27682766
if (gen_status == PYGEN_RETURN || gen_status == PYGEN_ERROR) {
2769-
PyObject *et, *ev, *tb;
2770-
27712767
if (result != NULL) {
27722768
/* The error is StopIteration and that means that
27732769
the underlying coroutine has resolved */
@@ -2794,52 +2790,39 @@ task_step_impl(asyncio_state *state, TaskObj *task, PyObject *exc)
27942790

27952791
if (PyErr_ExceptionMatches(state->asyncio_CancelledError)) {
27962792
/* CancelledError */
2797-
PyErr_Fetch(&et, &ev, &tb);
2798-
assert(et);
2799-
PyErr_NormalizeException(&et, &ev, &tb);
2800-
if (tb != NULL) {
2801-
PyException_SetTraceback(ev, tb);
2802-
Py_DECREF(tb);
2803-
}
2804-
Py_XDECREF(et);
2793+
2794+
PyObject *exc = PyErr_GetRaisedException();
2795+
assert(exc);
28052796

28062797
FutureObj *fut = (FutureObj*)task;
28072798
/* transfer ownership */
2808-
fut->fut_cancelled_exc = ev;
2799+
fut->fut_cancelled_exc = exc;
28092800

28102801
return future_cancel(state, fut, NULL);
28112802
}
28122803

28132804
/* Some other exception; pop it and call Task.set_exception() */
2814-
PyErr_Fetch(&et, &ev, &tb);
2815-
assert(et);
2816-
PyErr_NormalizeException(&et, &ev, &tb);
2817-
if (tb != NULL) {
2818-
PyException_SetTraceback(ev, tb);
2819-
}
2805+
PyObject *exc = PyErr_GetRaisedException();
2806+
assert(exc);
28202807

2821-
o = future_set_exception(state, (FutureObj*)task, ev);
2808+
o = future_set_exception(state, (FutureObj*)task, exc);
28222809
if (!o) {
28232810
/* An exception in Task.set_exception() */
2824-
Py_DECREF(et);
2825-
Py_XDECREF(tb);
2826-
Py_XDECREF(ev);
2811+
Py_DECREF(exc);
28272812
goto fail;
28282813
}
28292814
assert(o == Py_None);
28302815
Py_DECREF(o);
28312816

2832-
if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2833-
PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2817+
if (PyErr_GivenExceptionMatches(exc, PyExc_KeyboardInterrupt) ||
2818+
PyErr_GivenExceptionMatches(exc, PyExc_SystemExit))
28342819
{
28352820
/* We've got a KeyboardInterrupt or a SystemError; re-raise it */
2836-
PyErr_Restore(et, ev, tb);
2821+
PyErr_SetRaisedException(exc);
28372822
goto fail;
28382823
}
28392824

2840-
Py_DECREF(et);
2841-
Py_XDECREF(tb);
2842-
Py_XDECREF(ev);
2825+
Py_DECREF(exc);
28432826

28442827
Py_RETURN_NONE;
28452828
}
@@ -3059,10 +3042,9 @@ task_step(asyncio_state *state, TaskObj *task, PyObject *exc)
30593042
res = task_step_impl(state, task, exc);
30603043

30613044
if (res == NULL) {
3062-
PyObject *et, *ev, *tb;
3063-
PyErr_Fetch(&et, &ev, &tb);
3045+
PyObject *exc = PyErr_GetRaisedException();
30643046
leave_task(state, task->task_loop, (PyObject*)task);
3065-
_PyErr_ChainExceptions(et, ev, tb); /* Normalizes (et, ev, tb) */
3047+
_PyErr_ChainExceptions1(exc);
30663048
return NULL;
30673049
}
30683050
else {
@@ -3079,7 +3061,6 @@ task_step(asyncio_state *state, TaskObj *task, PyObject *exc)
30793061
static PyObject *
30803062
task_wakeup(TaskObj *task, PyObject *o)
30813063
{
3082-
PyObject *et, *ev, *tb;
30833064
PyObject *result;
30843065
assert(o);
30853066

@@ -3111,18 +3092,12 @@ task_wakeup(TaskObj *task, PyObject *o)
31113092
/* exception raised */
31123093
}
31133094

3114-
PyErr_Fetch(&et, &ev, &tb);
3115-
assert(et);
3116-
PyErr_NormalizeException(&et, &ev, &tb);
3117-
if (tb != NULL) {
3118-
PyException_SetTraceback(ev, tb);
3119-
}
3095+
PyObject *exc = PyErr_GetRaisedException();
3096+
assert(exc);
31203097

3121-
result = task_step(state, task, ev);
3098+
result = task_step(state, task, exc);
31223099

3123-
Py_DECREF(et);
3124-
Py_XDECREF(tb);
3125-
Py_XDECREF(ev);
3100+
Py_DECREF(exc);
31263101

31273102
return result;
31283103
}

Modules/_io/_iomodule.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -437,10 +437,9 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
437437

438438
error:
439439
if (result != NULL) {
440-
PyObject *exc, *val, *tb, *close_result;
441-
PyErr_Fetch(&exc, &val, &tb);
442-
close_result = PyObject_CallMethodNoArgs(result, &_Py_ID(close));
443-
_PyErr_ChainExceptions(exc, val, tb);
440+
PyObject *exc = PyErr_GetRaisedException();
441+
PyObject *close_result = PyObject_CallMethodNoArgs(result, &_Py_ID(close));
442+
_PyErr_ChainExceptions1(exc);
444443
Py_XDECREF(close_result);
445444
Py_DECREF(result);
446445
}

Modules/_io/bufferedio.c

+30-30
Original file line numberDiff line numberDiff line change
@@ -472,12 +472,13 @@ buffered_closed_get(buffered *self, void *context)
472472
static PyObject *
473473
buffered_close(buffered *self, PyObject *args)
474474
{
475-
PyObject *res = NULL, *exc = NULL, *val, *tb;
475+
PyObject *res = NULL;
476476
int r;
477477

478478
CHECK_INITIALIZED(self)
479-
if (!ENTER_BUFFERED(self))
479+
if (!ENTER_BUFFERED(self)) {
480480
return NULL;
481+
}
481482

482483
r = buffered_closed(self);
483484
if (r < 0)
@@ -497,12 +498,16 @@ buffered_close(buffered *self, PyObject *args)
497498
/* flush() will most probably re-take the lock, so drop it first */
498499
LEAVE_BUFFERED(self)
499500
res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
500-
if (!ENTER_BUFFERED(self))
501+
if (!ENTER_BUFFERED(self)) {
501502
return NULL;
502-
if (res == NULL)
503-
PyErr_Fetch(&exc, &val, &tb);
504-
else
503+
}
504+
PyObject *exc = NULL;
505+
if (res == NULL) {
506+
exc = PyErr_GetRaisedException();
507+
}
508+
else {
505509
Py_DECREF(res);
510+
}
506511

507512
res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close));
508513

@@ -512,7 +517,7 @@ buffered_close(buffered *self, PyObject *args)
512517
}
513518

514519
if (exc != NULL) {
515-
_PyErr_ChainExceptions(exc, val, tb);
520+
_PyErr_ChainExceptions1(exc);
516521
Py_CLEAR(res);
517522
}
518523

@@ -637,17 +642,14 @@ _set_BlockingIOError(const char *msg, Py_ssize_t written)
637642
static Py_ssize_t *
638643
_buffered_check_blocking_error(void)
639644
{
640-
PyObject *t, *v, *tb;
641-
PyOSErrorObject *err;
642-
643-
PyErr_Fetch(&t, &v, &tb);
644-
if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
645-
PyErr_Restore(t, v, tb);
645+
PyObject *exc = PyErr_GetRaisedException();
646+
if (exc == NULL || !PyErr_GivenExceptionMatches(exc, PyExc_BlockingIOError)) {
647+
PyErr_SetRaisedException(exc);
646648
return NULL;
647649
}
648-
err = (PyOSErrorObject *) v;
650+
PyOSErrorObject *err = (PyOSErrorObject *)exc;
649651
/* TODO: sanity check (err->written >= 0) */
650-
PyErr_Restore(t, v, tb);
652+
PyErr_SetRaisedException(exc);
651653
return &err->written;
652654
}
653655

@@ -749,13 +751,11 @@ _buffered_init(buffered *self)
749751
int
750752
_PyIO_trap_eintr(void)
751753
{
752-
PyObject *typ, *val, *tb;
753-
PyOSErrorObject *env_err;
754-
if (!PyErr_ExceptionMatches(PyExc_OSError))
754+
if (!PyErr_ExceptionMatches(PyExc_OSError)) {
755755
return 0;
756-
PyErr_Fetch(&typ, &val, &tb);
757-
PyErr_NormalizeException(&typ, &val, &tb);
758-
env_err = (PyOSErrorObject *) val;
756+
}
757+
PyObject *exc = PyErr_GetRaisedException();
758+
PyOSErrorObject *env_err = (PyOSErrorObject *)exc;
759759
assert(env_err != NULL);
760760
if (env_err->myerrno != NULL) {
761761
assert(EINTR > 0 && EINTR < INT_MAX);
@@ -764,14 +764,12 @@ _PyIO_trap_eintr(void)
764764
int myerrno = PyLong_AsLongAndOverflow(env_err->myerrno, &overflow);
765765
PyErr_Clear();
766766
if (myerrno == EINTR) {
767-
Py_DECREF(typ);
768-
Py_DECREF(val);
769-
Py_XDECREF(tb);
767+
Py_DECREF(exc);
770768
return 1;
771769
}
772770
}
773771
/* This silences any error set by PyObject_RichCompareBool() */
774-
PyErr_Restore(typ, val, tb);
772+
PyErr_SetRaisedException(exc);
775773
return 0;
776774
}
777775

@@ -2228,15 +2226,17 @@ bufferedrwpair_writable(rwpair *self, PyObject *Py_UNUSED(ignored))
22282226
static PyObject *
22292227
bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored))
22302228
{
2231-
PyObject *exc = NULL, *val, *tb;
2229+
PyObject *exc = NULL;
22322230
PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL);
2233-
if (ret == NULL)
2234-
PyErr_Fetch(&exc, &val, &tb);
2235-
else
2231+
if (ret == NULL) {
2232+
exc = PyErr_GetRaisedException();
2233+
}
2234+
else {
22362235
Py_DECREF(ret);
2236+
}
22372237
ret = _forward_call(self->reader, &_Py_ID(close), NULL);
22382238
if (exc != NULL) {
2239-
_PyErr_ChainExceptions(exc, val, tb);
2239+
_PyErr_ChainExceptions1(exc);
22402240
Py_CLEAR(ret);
22412241
}
22422242
return ret;

Modules/_io/fileio.c

+17-14
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,13 @@ static PyObject *
8888
fileio_dealloc_warn(fileio *self, PyObject *source)
8989
{
9090
if (self->fd >= 0 && self->closefd) {
91-
PyObject *exc, *val, *tb;
92-
PyErr_Fetch(&exc, &val, &tb);
91+
PyObject *exc = PyErr_GetRaisedException();
9392
if (PyErr_ResourceWarning(source, 1, "unclosed file %R", source)) {
9493
/* Spurious errors can appear at shutdown */
9594
if (PyErr_ExceptionMatches(PyExc_Warning))
9695
PyErr_WriteUnraisable((PyObject *) self);
9796
}
98-
PyErr_Restore(exc, val, tb);
97+
PyErr_SetRaisedException(exc);
9998
}
10099
Py_RETURN_NONE;
101100
}
@@ -140,28 +139,33 @@ _io_FileIO_close_impl(fileio *self)
140139
/*[clinic end generated code: output=7737a319ef3bad0b input=f35231760d54a522]*/
141140
{
142141
PyObject *res;
143-
PyObject *exc, *val, *tb;
142+
PyObject *exc;
144143
int rc;
145144
res = PyObject_CallMethodOneArg((PyObject*)&PyRawIOBase_Type,
146145
&_Py_ID(close), (PyObject *)self);
147146
if (!self->closefd) {
148147
self->fd = -1;
149148
return res;
150149
}
151-
if (res == NULL)
152-
PyErr_Fetch(&exc, &val, &tb);
150+
if (res == NULL) {
151+
exc = PyErr_GetRaisedException();
152+
}
153153
if (self->finalizing) {
154154
PyObject *r = fileio_dealloc_warn(self, (PyObject *) self);
155-
if (r)
155+
if (r) {
156156
Py_DECREF(r);
157-
else
157+
}
158+
else {
158159
PyErr_Clear();
160+
}
159161
}
160162
rc = internal_close(self);
161-
if (res == NULL)
162-
_PyErr_ChainExceptions(exc, val, tb);
163-
if (rc < 0)
163+
if (res == NULL) {
164+
_PyErr_ChainExceptions1(exc);
165+
}
166+
if (rc < 0) {
164167
Py_CLEAR(res);
168+
}
165169
return res;
166170
}
167171

@@ -487,10 +491,9 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
487491
if (!fd_is_own)
488492
self->fd = -1;
489493
if (self->fd >= 0) {
490-
PyObject *exc, *val, *tb;
491-
PyErr_Fetch(&exc, &val, &tb);
494+
PyObject *exc = PyErr_GetRaisedException();
492495
internal_close(self);
493-
_PyErr_ChainExceptions(exc, val, tb);
496+
_PyErr_ChainExceptions1(exc);
494497
}
495498

496499
done:

0 commit comments

Comments
 (0)