Skip to content

Commit 1a4d1c1

Browse files
authored
bpo-46070: _PyGC_Fini() untracks objects (GH-30577)
Py_EndInterpreter() now explicitly untracks all objects currently tracked by the GC. Previously, if an object was used later by another interpreter, calling PyObject_GC_UnTrack() on the object crashed if the previous or the next object of the PyGC_Head structure became a dangling pointer.
1 parent 6be8489 commit 1a4d1c1

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:c:func:`Py_EndInterpreter` now explicitly untracks all objects currently
2+
tracked by the GC. Previously, if an object was used later by another
3+
interpreter, calling :c:func:`PyObject_GC_UnTrack` on the object crashed if the
4+
previous or the next object of the :c:type:`PyGC_Head` structure became a
5+
dangling pointer. Patch by Victor Stinner.

Modules/gcmodule.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,12 +2161,36 @@ _PyGC_DumpShutdownStats(PyInterpreterState *interp)
21612161
}
21622162
}
21632163

2164+
2165+
static void
2166+
gc_fini_untrack(PyGC_Head *list)
2167+
{
2168+
PyGC_Head *gc;
2169+
for (gc = GC_NEXT(list); gc != list; gc = GC_NEXT(list)) {
2170+
PyObject *op = FROM_GC(gc);
2171+
_PyObject_GC_UNTRACK(op);
2172+
}
2173+
}
2174+
2175+
21642176
void
21652177
_PyGC_Fini(PyInterpreterState *interp)
21662178
{
21672179
GCState *gcstate = &interp->gc;
21682180
Py_CLEAR(gcstate->garbage);
21692181
Py_CLEAR(gcstate->callbacks);
2182+
2183+
if (!_Py_IsMainInterpreter(interp)) {
2184+
// bpo-46070: Explicitly untrack all objects currently tracked by the
2185+
// GC. Otherwise, if an object is used later by another interpreter,
2186+
// calling PyObject_GC_UnTrack() on the object crashs if the previous
2187+
// or the next object of the PyGC_Head structure became a dangling
2188+
// pointer.
2189+
for (int i = 0; i < NUM_GENERATIONS; i++) {
2190+
PyGC_Head *gen = GEN_HEAD(gcstate, i);
2191+
gc_fini_untrack(gen);
2192+
}
2193+
}
21702194
}
21712195

21722196
/* for debugging */

0 commit comments

Comments
 (0)