mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	GH-100964: Break cycles involving exception state when returning from generator (GH-107563)
This commit is contained in:
		
							parent
							
								
									dd693d6320
								
							
						
					
					
						commit
						0d30a5a409
					
				
					 3 changed files with 7 additions and 5 deletions
				
			
		|  | @ -0,0 +1,2 @@ | ||||||
|  | Clear generators' exception state after ``return`` to break reference | ||||||
|  | cycles. | ||||||
|  | @ -149,14 +149,16 @@ gen_dealloc(PyGenObject *gen) | ||||||
|         gen->gi_frame_state = FRAME_CLEARED; |         gen->gi_frame_state = FRAME_CLEARED; | ||||||
|         frame->previous = NULL; |         frame->previous = NULL; | ||||||
|         _PyFrame_ClearExceptCode(frame); |         _PyFrame_ClearExceptCode(frame); | ||||||
|  |         _PyErr_ClearExcState(&gen->gi_exc_state); | ||||||
|     } |     } | ||||||
|  |     assert(gen->gi_exc_state.exc_value == NULL); | ||||||
|     if (_PyGen_GetCode(gen)->co_flags & CO_COROUTINE) { |     if (_PyGen_GetCode(gen)->co_flags & CO_COROUTINE) { | ||||||
|         Py_CLEAR(((PyCoroObject *)gen)->cr_origin_or_finalizer); |         Py_CLEAR(((PyCoroObject *)gen)->cr_origin_or_finalizer); | ||||||
|     } |     } | ||||||
|     Py_DECREF(_PyGen_GetCode(gen)); |     Py_DECREF(_PyGen_GetCode(gen)); | ||||||
|     Py_CLEAR(gen->gi_name); |     Py_CLEAR(gen->gi_name); | ||||||
|     Py_CLEAR(gen->gi_qualname); |     Py_CLEAR(gen->gi_qualname); | ||||||
|     _PyErr_ClearExcState(&gen->gi_exc_state); | 
 | ||||||
|     PyObject_GC_Del(gen); |     PyObject_GC_Del(gen); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -252,10 +254,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, | ||||||
|             !PyErr_ExceptionMatches(PyExc_StopAsyncIteration)); |             !PyErr_ExceptionMatches(PyExc_StopAsyncIteration)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* generator can't be rerun, so release the frame */ |     assert(gen->gi_exc_state.exc_value == NULL); | ||||||
|     /* first clean reference cycle through stored exception traceback */ |  | ||||||
|     _PyErr_ClearExcState(&gen->gi_exc_state); |  | ||||||
| 
 |  | ||||||
|     assert(gen->gi_frame_state == FRAME_CLEARED); |     assert(gen->gi_frame_state == FRAME_CLEARED); | ||||||
|     *presult = result; |     *presult = result; | ||||||
|     return result ? PYGEN_RETURN : PYGEN_ERROR; |     return result ? PYGEN_RETURN : PYGEN_ERROR; | ||||||
|  |  | ||||||
|  | @ -1466,6 +1466,7 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame) | ||||||
|     tstate->c_recursion_remaining--; |     tstate->c_recursion_remaining--; | ||||||
|     assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame); |     assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame); | ||||||
|     _PyFrame_ClearExceptCode(frame); |     _PyFrame_ClearExceptCode(frame); | ||||||
|  |     _PyErr_ClearExcState(&gen->gi_exc_state); | ||||||
|     tstate->c_recursion_remaining++; |     tstate->c_recursion_remaining++; | ||||||
|     frame->previous = NULL; |     frame->previous = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Mark Shannon
						Mark Shannon