@@ -189,6 +189,8 @@ parse_frame_object(
189189 set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to read interpreter frame" );
190190 return -1 ;
191191 }
192+ STATS_INC (unwinder , memory_reads );
193+ STATS_ADD (unwinder , memory_bytes_read , SIZEOF_INTERP_FRAME );
192194
193195 * previous_frame = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .previous );
194196 uintptr_t code_object = GET_MEMBER_NO_TAG (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable );
@@ -477,23 +479,30 @@ try_full_cache_hit(
477479 return -1 ;
478480 }
479481
480- // Add current frame if valid
482+ // Get cached parent frames first (before modifying frame_info)
483+ Py_ssize_t cached_size = PyList_GET_SIZE (entry -> frame_list );
484+ PyObject * parent_slice = NULL ;
485+ if (cached_size > 1 ) {
486+ parent_slice = PyList_GetSlice (entry -> frame_list , 1 , cached_size );
487+ if (!parent_slice ) {
488+ Py_XDECREF (current_frame );
489+ return -1 ;
490+ }
491+ }
492+
493+ // Now safe to modify frame_info - add current frame if valid
481494 if (current_frame != NULL ) {
482495 if (PyList_Append (frame_info , current_frame ) < 0 ) {
483496 Py_DECREF (current_frame );
497+ Py_XDECREF (parent_slice );
484498 return -1 ;
485499 }
486500 Py_DECREF (current_frame );
487501 STATS_ADD (unwinder , frames_read_from_memory , 1 );
488502 }
489503
490- // Extend with cached parent frames (from index 1 onwards, skipping the current frame)
491- Py_ssize_t cached_size = PyList_GET_SIZE (entry -> frame_list );
492- if (cached_size > 1 ) {
493- PyObject * parent_slice = PyList_GetSlice (entry -> frame_list , 1 , cached_size );
494- if (!parent_slice ) {
495- return -1 ;
496- }
504+ // Extend with cached parent frames
505+ if (parent_slice ) {
497506 Py_ssize_t cur_size = PyList_GET_SIZE (frame_info );
498507 int result = PyList_SetSlice (frame_info , cur_size , cur_size , parent_slice );
499508 Py_DECREF (parent_slice );
@@ -569,7 +578,9 @@ collect_frames_with_cache(
569578 }
570579
571580 // Store in cache (frame_cache_store handles truncation if num_addrs > FRAME_CACHE_MAX_FRAMES)
572- frame_cache_store (unwinder , thread_id , frame_info , addrs , num_addrs );
581+ if (frame_cache_store (unwinder , thread_id , frame_info , addrs , num_addrs ) < 0 ) {
582+ return -1 ;
583+ }
573584
574585 return 0 ;
575586}
0 commit comments