diff options
author | Mark Shannon <mark@hotpy.org> | 2017-10-22 21:41:51 (GMT) |
---|---|---|
committer | Antoine Pitrou <pitrou@free.fr> | 2017-10-22 21:41:51 (GMT) |
commit | ae3087c6382011c47db82fea4d05f8bbf514265d (patch) | |
tree | c5d832a760d9898700f1ca397a5a305734b3d77a /Objects | |
parent | 91dc64ba3f51100540b2ab6c6cd72c3bb18a6d49 (diff) | |
download | cpython-ae3087c6382011c47db82fea4d05f8bbf514265d.zip cpython-ae3087c6382011c47db82fea4d05f8bbf514265d.tar.gz cpython-ae3087c6382011c47db82fea4d05f8bbf514265d.tar.bz2 |
Move exc state to generator. Fixes bpo-25612 (#1773)
Move exception state information from frame objects to coroutine (generator/thread) object where it belongs.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/frameobject.c | 13 | ||||
-rw-r--r-- | Objects/genobject.c | 46 |
2 files changed, 36 insertions, 23 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 8739596..6ab3a22 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -379,8 +379,7 @@ static PyGetSetDef frame_getsetlist[] = { * ob_type, ob_size, f_code, f_valuestack; - * f_locals, f_trace, - f_exc_type, f_exc_value, f_exc_traceback are NULL; + * f_locals, f_trace are NULL; * f_localsplus does not require re-allocation and the local variables in f_localsplus are NULL. @@ -438,9 +437,6 @@ frame_dealloc(PyFrameObject *f) Py_DECREF(f->f_globals); Py_CLEAR(f->f_locals); Py_CLEAR(f->f_trace); - Py_CLEAR(f->f_exc_type); - Py_CLEAR(f->f_exc_value); - Py_CLEAR(f->f_exc_traceback); co = f->f_code; if (co->co_zombieframe == NULL) @@ -469,9 +465,6 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg) Py_VISIT(f->f_globals); Py_VISIT(f->f_locals); Py_VISIT(f->f_trace); - Py_VISIT(f->f_exc_type); - Py_VISIT(f->f_exc_value); - Py_VISIT(f->f_exc_traceback); /* locals */ slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars); @@ -502,9 +495,6 @@ frame_tp_clear(PyFrameObject *f) f->f_stacktop = NULL; f->f_executing = 0; - Py_CLEAR(f->f_exc_type); - Py_CLEAR(f->f_exc_value); - Py_CLEAR(f->f_exc_traceback); Py_CLEAR(f->f_trace); /* locals */ @@ -698,7 +688,6 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, f->f_localsplus[i] = NULL; f->f_locals = NULL; f->f_trace = NULL; - f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL; } f->f_stacktop = f->f_valuestack; f->f_builtins = builtins; diff --git a/Objects/genobject.c b/Objects/genobject.c index 5d5798c..7793a54 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -16,6 +16,15 @@ static char *NON_INIT_CORO_MSG = "can't send non-None value to a " static char *ASYNC_GEN_IGNORED_EXIT_MSG = "async generator ignored GeneratorExit"; +static inline int +exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg) +{ + Py_VISIT(exc_state->exc_type); + Py_VISIT(exc_state->exc_value); + Py_VISIT(exc_state->exc_traceback); + return 0; +} + static int gen_traverse(PyGenObject *gen, visitproc visit, void *arg) { @@ -23,7 +32,7 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg) Py_VISIT(gen->gi_code); Py_VISIT(gen->gi_name); Py_VISIT(gen->gi_qualname); - return 0; + return exc_state_traverse(&gen->gi_exc_state, visit, arg); } void @@ -87,6 +96,21 @@ _PyGen_Finalize(PyObject *self) PyErr_Restore(error_type, error_value, error_traceback); } +static inline void +exc_state_clear(_PyErr_StackItem *exc_state) +{ + PyObject *t, *v, *tb; + t = exc_state->exc_type; + v = exc_state->exc_value; + tb = exc_state->exc_traceback; + exc_state->exc_type = NULL; + exc_state->exc_value = NULL; + exc_state->exc_traceback = NULL; + Py_XDECREF(t); + Py_XDECREF(v); + Py_XDECREF(tb); +} + static void gen_dealloc(PyGenObject *gen) { @@ -116,6 +140,7 @@ gen_dealloc(PyGenObject *gen) Py_CLEAR(gen->gi_code); Py_CLEAR(gen->gi_name); Py_CLEAR(gen->gi_qualname); + exc_state_clear(&gen->gi_exc_state); PyObject_GC_Del(gen); } @@ -187,7 +212,11 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing) f->f_back = tstate->frame; gen->gi_running = 1; + gen->gi_exc_state.previous_item = tstate->exc_info; + tstate->exc_info = &gen->gi_exc_state; result = PyEval_EvalFrameEx(f, exc); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; gen->gi_running = 0; /* Don't keep the reference to f_back any longer than necessary. It @@ -281,16 +310,7 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing) if (!result || f->f_stacktop == NULL) { /* generator can't be rerun, so release the frame */ /* first clean reference cycle through stored exception traceback */ - PyObject *t, *v, *tb; - t = f->f_exc_type; - v = f->f_exc_value; - tb = f->f_exc_traceback; - f->f_exc_type = NULL; - f->f_exc_value = NULL; - f->f_exc_traceback = NULL; - Py_XDECREF(t); - Py_XDECREF(v); - Py_XDECREF(tb); + exc_state_clear(&gen->gi_exc_state); gen->gi_frame->f_gen = NULL; gen->gi_frame = NULL; Py_DECREF(f); @@ -810,6 +830,10 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, gen->gi_code = (PyObject *)(f->f_code); gen->gi_running = 0; gen->gi_weakreflist = NULL; + gen->gi_exc_state.exc_type = NULL; + gen->gi_exc_state.exc_value = NULL; + gen->gi_exc_state.exc_traceback = NULL; + gen->gi_exc_state.previous_item = NULL; if (name != NULL) gen->gi_name = name; else |