mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	A previous commit introduced a bug to `interpreter_clear()`: it set `interp->ceval.instrumentation_version` to 0, without making the corresponding change to `tstate->eval_breaker` (which holds a thread-local copy of the version). After this happens, Python code can still run due to object finalizers during a GC, and the version check in bytecodes.c will see a different result than the one in instrumentation.c causing an infinite loop. The fix itself is straightforward: clear `tstate->eval_breaker` when clearing `interp->ceval.instrumentation_version`.
		
			
				
	
	
		
			30 lines
		
	
	
	
		
			727 B
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			30 lines
		
	
	
	
		
			727 B
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/env python3
 | 
						|
 | 
						|
# gh-115832: An object destructor running during the final GC of interpreter
 | 
						|
# shutdown triggered an infinite loop in the instrumentation code.
 | 
						|
 | 
						|
import sys
 | 
						|
 | 
						|
class CallableCycle:
 | 
						|
    def __init__(self):
 | 
						|
        self._cycle = self
 | 
						|
 | 
						|
    def __del__(self):
 | 
						|
        pass
 | 
						|
 | 
						|
    def __call__(self, code, instruction_offset):
 | 
						|
        pass
 | 
						|
 | 
						|
def tracefunc(frame, event, arg):
 | 
						|
    pass
 | 
						|
 | 
						|
def main():
 | 
						|
    tool_id = sys.monitoring.PROFILER_ID
 | 
						|
    event_id = sys.monitoring.events.PY_START
 | 
						|
 | 
						|
    sys.monitoring.use_tool_id(tool_id, "test profiler")
 | 
						|
    sys.monitoring.set_events(tool_id, event_id)
 | 
						|
    sys.monitoring.register_callback(tool_id, event_id, CallableCycle())
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    sys.exit(main())
 |