@@ -105,34 +105,40 @@ get_gc_stats_from_interpreter_state(RuntimeOffsets *offsets,
105105 struct gc_stats stats ;
106106 uintptr_t sequence_address = gc_stats_addr
107107 + 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- }
116- if (_Py_RemoteDebug_ReadRemoteMemory (& offsets -> handle ,
117- gc_stats_addr ,
118- sizeof (stats ),
119- & stats ) < 0 ) {
120- set_exception_cause (offsets , PyExc_RuntimeError , "Failed to read GC state" );
121- return -1 ;
122- }
108+ /* A short GC update may finish before a second attempt. */
109+ for (int attempt = 0 ; attempt < 2 ; attempt ++ ) {
110+ uint32_t before ;
111+ if (_Py_RemoteDebug_ReadRemoteMemory (& offsets -> handle ,
112+ sequence_address ,
113+ sizeof (before ), & before ) < 0 ) {
114+ set_exception_cause (offsets , PyExc_RuntimeError ,
115+ "Failed to read GC update sequence" );
116+ return -1 ;
117+ }
118+ if (_Py_RemoteDebug_ReadRemoteMemory (& offsets -> handle ,
119+ gc_stats_addr ,
120+ sizeof (stats ),
121+ & stats ) < 0 ) {
122+ set_exception_cause (offsets , PyExc_RuntimeError , "Failed to read GC state" );
123+ return -1 ;
124+ }
123125
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 ;
126+ uint32_t after ;
127+ if (_Py_RemoteDebug_ReadRemoteMemory (& offsets -> handle ,
128+ sequence_address ,
129+ sizeof (after ), & after ) < 0 ) {
130+ set_exception_cause (offsets , PyExc_RuntimeError ,
131+ "Failed to read GC update sequence" );
132+ return -1 ;
133+ }
134+ if (before == after && before == stats .update_seq && !(after & 1 )) {
135+ break ;
136+ }
137+ if (attempt == 1 ) {
138+ PyErr_SetString (PyExc_RuntimeError ,
139+ "GC stats changed while being read; retry later" );
140+ return -1 ;
141+ }
136142 }
137143
138144 if (read_gc_stats (& stats , iid , ctx -> result ,
0 commit comments