@@ -16,14 +16,23 @@ static char *NON_INIT_CORO_MSG = "can't send non-None value to a "
1616static char * ASYNC_GEN_IGNORED_EXIT_MSG =
1717 "async generator ignored GeneratorExit" ;
1818
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+
1928static int
2029gen_traverse (PyGenObject * gen , visitproc visit , void * arg )
2130{
2231 Py_VISIT ((PyObject * )gen -> gi_frame );
2332 Py_VISIT (gen -> gi_code );
2433 Py_VISIT (gen -> gi_name );
2534 Py_VISIT (gen -> gi_qualname );
26- return 0 ;
35+ return exc_state_traverse ( & gen -> gi_exc_state , visit , arg ) ;
2736}
2837
2938void
@@ -87,6 +96,21 @@ _PyGen_Finalize(PyObject *self)
8796 PyErr_Restore (error_type , error_value , error_traceback );
8897}
8998
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+
90114static void
91115gen_dealloc (PyGenObject * gen )
92116{
@@ -116,6 +140,7 @@ gen_dealloc(PyGenObject *gen)
116140 Py_CLEAR (gen -> gi_code );
117141 Py_CLEAR (gen -> gi_name );
118142 Py_CLEAR (gen -> gi_qualname );
143+ exc_state_clear (& gen -> gi_exc_state );
119144 PyObject_GC_Del (gen );
120145}
121146
@@ -187,7 +212,11 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
187212 f -> f_back = tstate -> frame ;
188213
189214 gen -> gi_running = 1 ;
215+ gen -> gi_exc_state .previous_item = tstate -> exc_info ;
216+ tstate -> exc_info = & gen -> gi_exc_state ;
190217 result = PyEval_EvalFrameEx (f , exc );
218+ tstate -> exc_info = gen -> gi_exc_state .previous_item ;
219+ gen -> gi_exc_state .previous_item = NULL ;
191220 gen -> gi_running = 0 ;
192221
193222 /* 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)
281310 if (!result || f -> f_stacktop == NULL ) {
282311 /* generator can't be rerun, so release the frame */
283312 /* 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 );
294314 gen -> gi_frame -> f_gen = NULL ;
295315 gen -> gi_frame = NULL ;
296316 Py_DECREF (f );
@@ -810,6 +830,10 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
810830 gen -> gi_code = (PyObject * )(f -> f_code );
811831 gen -> gi_running = 0 ;
812832 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 ;
813837 if (name != NULL )
814838 gen -> gi_name = name ;
815839 else
0 commit comments