@@ -103,6 +103,16 @@ get_gc_stats_from_interpreter_state(RuntimeOffsets *offsets,
103103 }
104104
105105 struct gc_stats stats ;
106+ uintptr_t sequence_address = gc_stats_addr
107+ + offsetof(struct gc_stats , update_seq );
108+ uint32_t before ;
109+ if (_Py_RemoteDebug_ReadRemoteMemory (& offsets -> handle ,
110+ sequence_address ,
111+ sizeof (before ), & before ) < 0 ) {
112+ set_exception_cause (offsets , PyExc_RuntimeError ,
113+ "Failed to read GC update sequence" );
114+ return -1 ;
115+ }
106116 if (_Py_RemoteDebug_ReadRemoteMemory (& offsets -> handle ,
107117 gc_stats_addr ,
108118 sizeof (stats ),
@@ -111,6 +121,20 @@ get_gc_stats_from_interpreter_state(RuntimeOffsets *offsets,
111121 return -1 ;
112122 }
113123
124+ uint32_t after ;
125+ if (_Py_RemoteDebug_ReadRemoteMemory (& offsets -> handle ,
126+ sequence_address ,
127+ sizeof (after ), & after ) < 0 ) {
128+ set_exception_cause (offsets , PyExc_RuntimeError ,
129+ "Failed to read GC update sequence" );
130+ return -1 ;
131+ }
132+ if (before != after || before != stats .update_seq || (after & 1 )) {
133+ PyErr_SetString (PyExc_RuntimeError ,
134+ "GC stats changed while being read; retry later" );
135+ return -1 ;
136+ }
137+
114138 if (read_gc_stats (& stats , iid , ctx -> result ,
115139 ctx -> gc_stats_info_type ) < 0 ) {
116140 set_exception_cause (offsets , PyExc_RuntimeError , "Failed to populate GC stats result" );
0 commit comments