Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

(cherry picked from commit 1a4d1c1)
  • Loading branch information
vstinner committed Jan 13, 2022
commit 2cc9e388629372e53ab9b8ed48714ac5528f0480
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
:c:func:`Py_EndInterpreter` now explicitly untracks all objects currently
tracked by the GC. Previously, if an object was used later by another
interpreter, calling :c:func:`PyObject_GC_UnTrack` on the object crashed if the
previous or the next object of the :c:type:`PyGC_Head` structure became a
dangling pointer. Patch by Victor Stinner.
24 changes: 24 additions & 0 deletions Modules/gcmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2149,12 +2149,36 @@ _PyGC_DumpShutdownStats(PyThreadState *tstate)
}
}


static void
gc_fini_untrack(PyGC_Head *list)
{
PyGC_Head *gc;
for (gc = GC_NEXT(list); gc != list; gc = GC_NEXT(list)) {
PyObject *op = FROM_GC(gc);
_PyObject_GC_UNTRACK(op);
}
}


void
_PyGC_Fini(PyThreadState *tstate)
{
GCState *gcstate = &tstate->interp->gc;
Py_CLEAR(gcstate->garbage);
Py_CLEAR(gcstate->callbacks);

if (!_Py_IsMainInterpreter(tstate)) {
// bpo-46070: Explicitly untrack all objects currently tracked by the
// GC. Otherwise, if an object is used later by another interpreter,
// calling PyObject_GC_UnTrack() on the object crashs if the previous
// or the next object of the PyGC_Head structure became a dangling
// pointer.
for (int i = 0; i < NUM_GENERATIONS; i++) {
PyGC_Head *gen = GEN_HEAD(gcstate, i);
gc_fini_untrack(gen);
}
}
}

/* for debugging */
Expand Down