Move exc state to generator. Fixes bpo-25612 (#1773) · python/cpython@ae3087c (original) (raw)
`@@ -16,14 +16,23 @@ static char *NON_INIT_CORO_MSG = "can't send non-None value to a "
`
16
16
`static char *ASYNC_GEN_IGNORED_EXIT_MSG =
`
17
17
`"async generator ignored GeneratorExit";
`
18
18
``
``
19
`+
static inline int
`
``
20
`+
exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg)
`
``
21
`+
{
`
``
22
`+
Py_VISIT(exc_state->exc_type);
`
``
23
`+
Py_VISIT(exc_state->exc_value);
`
``
24
`+
Py_VISIT(exc_state->exc_traceback);
`
``
25
`+
return 0;
`
``
26
`+
}
`
``
27
+
19
28
`static int
`
20
29
`gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
`
21
30
`{
`
22
31
`Py_VISIT((PyObject *)gen->gi_frame);
`
23
32
`Py_VISIT(gen->gi_code);
`
24
33
`Py_VISIT(gen->gi_name);
`
25
34
`Py_VISIT(gen->gi_qualname);
`
26
``
`-
return 0;
`
``
35
`+
return exc_state_traverse(&gen->gi_exc_state, visit, arg);
`
27
36
`}
`
28
37
``
29
38
`void
`
`@@ -87,6 +96,21 @@ _PyGen_Finalize(PyObject *self)
`
87
96
`PyErr_Restore(error_type, error_value, error_traceback);
`
88
97
`}
`
89
98
``
``
99
`+
static inline void
`
``
100
`+
exc_state_clear(_PyErr_StackItem *exc_state)
`
``
101
`+
{
`
``
102
`+
PyObject *t, *v, *tb;
`
``
103
`+
t = exc_state->exc_type;
`
``
104
`+
v = exc_state->exc_value;
`
``
105
`+
tb = exc_state->exc_traceback;
`
``
106
`+
exc_state->exc_type = NULL;
`
``
107
`+
exc_state->exc_value = NULL;
`
``
108
`+
exc_state->exc_traceback = NULL;
`
``
109
`+
Py_XDECREF(t);
`
``
110
`+
Py_XDECREF(v);
`
``
111
`+
Py_XDECREF(tb);
`
``
112
`+
}
`
``
113
+
90
114
`static void
`
91
115
`gen_dealloc(PyGenObject *gen)
`
92
116
`{
`
`@@ -116,6 +140,7 @@ gen_dealloc(PyGenObject *gen)
`
116
140
`Py_CLEAR(gen->gi_code);
`
117
141
`Py_CLEAR(gen->gi_name);
`
118
142
`Py_CLEAR(gen->gi_qualname);
`
``
143
`+
exc_state_clear(&gen->gi_exc_state);
`
119
144
`PyObject_GC_Del(gen);
`
120
145
`}
`
121
146
``
`@@ -187,7 +212,11 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
`
187
212
`f->f_back = tstate->frame;
`
188
213
``
189
214
`gen->gi_running = 1;
`
``
215
`+
gen->gi_exc_state.previous_item = tstate->exc_info;
`
``
216
`+
tstate->exc_info = &gen->gi_exc_state;
`
190
217
`result = PyEval_EvalFrameEx(f, exc);
`
``
218
`+
tstate->exc_info = gen->gi_exc_state.previous_item;
`
``
219
`+
gen->gi_exc_state.previous_item = NULL;
`
191
220
`gen->gi_running = 0;
`
192
221
``
193
222
`/* 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)
`
281
310
`if (!result || f->f_stacktop == NULL) {
`
282
311
`/* generator can't be rerun, so release the frame */
`
283
312
`/* first clean reference cycle through stored exception traceback */
`
284
``
`-
PyObject *t, *v, *tb;
`
285
``
`-
t = f->f_exc_type;
`
286
``
`-
v = f->f_exc_value;
`
287
``
`-
tb = f->f_exc_traceback;
`
288
``
`-
f->f_exc_type = NULL;
`
289
``
`-
f->f_exc_value = NULL;
`
290
``
`-
f->f_exc_traceback = NULL;
`
291
``
`-
Py_XDECREF(t);
`
292
``
`-
Py_XDECREF(v);
`
293
``
`-
Py_XDECREF(tb);
`
``
313
`+
exc_state_clear(&gen->gi_exc_state);
`
294
314
`gen->gi_frame->f_gen = NULL;
`
295
315
`gen->gi_frame = NULL;
`
296
316
`Py_DECREF(f);
`
`@@ -810,6 +830,10 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
`
810
830
`gen->gi_code = (PyObject *)(f->f_code);
`
811
831
`gen->gi_running = 0;
`
812
832
`gen->gi_weakreflist = NULL;
`
``
833
`+
gen->gi_exc_state.exc_type = NULL;
`
``
834
`+
gen->gi_exc_state.exc_value = NULL;
`
``
835
`+
gen->gi_exc_state.exc_traceback = NULL;
`
``
836
`+
gen->gi_exc_state.previous_item = NULL;
`
813
837
`if (name != NULL)
`
814
838
`gen->gi_name = name;
`
815
839
`else
`