Skip to content

Commit 5e8323a

Browse files
committed
Move exc_context setting into _gen_throw and restore previous exception
This avoids accidentally overriding the exception state of the current thread when calling `.throw()` (what happened in the previous commit)
1 parent c0e7400 commit 5e8323a

1 file changed

Lines changed: 17 additions & 9 deletions

File tree

‎Objects/genobject.c‎

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -462,11 +462,13 @@ and may be removed in a future version of Python.");
462462

463463
static PyObject *
464464
_gen_throw(PyGenObject *gen, int close_on_genexit,
465-
PyObject *typ, PyObject *val, PyObject *tb)
465+
PyObject *typ, PyObject *val, PyObject *tb,
466+
PyObject *exc_context)
466467
{
467468
PyObject *yf = _PyGen_yf(gen);
468469

469470
if (yf) {
471+
assert(exc_context == NULL);
470472
_PyInterpreterFrame *frame = &gen->gi_iframe;
471473
PyObject *ret;
472474
int err;
@@ -502,7 +504,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
502504
PyFrameState state = gen->gi_frame_state;
503505
gen->gi_frame_state = FRAME_EXECUTING;
504506
ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
505-
typ, val, tb);
507+
typ, val, tb, NULL);
506508
gen->gi_frame_state = state;
507509
tstate->current_frame = prev;
508510
frame->previous = NULL;
@@ -581,8 +583,17 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
581583
goto failed_throw;
582584
}
583585

586+
/* hide the current thread's exception context from the generator */
587+
PyThreadState *tstate = _PyThreadState_GET();
588+
assert(tstate != NULL);
589+
PyObject *prev_exc = tstate->exc_info->exc_value;
590+
tstate->exc_info->exc_value = (exc_context == NULL ? Py_None : exc_context);
591+
584592
PyErr_Restore(typ, val, tb);
585-
return gen_send_ex(gen, Py_None, 1, 0);
593+
PyObject* ret = gen_send_ex(gen, Py_None, 1, 0);
594+
595+
tstate->exc_info->exc_value = prev_exc;
596+
return ret;
586597

587598
failed_throw:
588599
/* Didn't use our arguments, so restore their original refcounts */
@@ -648,10 +659,7 @@ gen_throw(PyObject *op, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnam
648659
return NULL;
649660
}
650661
}
651-
// update the generator's current exception context before throwing the
652-
// exception into it
653-
PyErr_SetHandledException(exc_context == NULL ? Py_None : exc_context);
654-
return _gen_throw(gen, 1, typ, val, tb);
662+
return _gen_throw(gen, 1, typ, val, tb, exc_context);
655663
}
656664

657665

@@ -2182,7 +2190,7 @@ async_gen_athrow_send(PyObject *self, PyObject *arg)
21822190
retval = _gen_throw((PyGenObject *)gen,
21832191
0, /* Do not close generator when
21842192
PyExc_GeneratorExit is passed */
2185-
PyExc_GeneratorExit, NULL, NULL);
2193+
PyExc_GeneratorExit, NULL, NULL, NULL);
21862194

21872195
if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
21882196
Py_DECREF(retval);
@@ -2201,7 +2209,7 @@ async_gen_athrow_send(PyObject *self, PyObject *arg)
22012209
retval = _gen_throw((PyGenObject *)gen,
22022210
0, /* Do not close generator when
22032211
PyExc_GeneratorExit is passed */
2204-
typ, val, tb);
2212+
typ, val, tb, NULL);
22052213
retval = async_gen_unwrap_value(o->agt_gen, retval);
22062214
}
22072215
if (retval == NULL) {

0 commit comments

Comments
 (0)