Skip to content

Commit 577305e

Browse files
committed
gh-155811: Retry an inconsistent GC snapshot once
1 parent 424b95f commit 577305e

1 file changed

Lines changed: 33 additions & 27 deletions

File tree

‎Modules/_remote_debugging/gc_stats.c‎

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)