summaryrefslogtreecommitdiffstats
path: root/Modules/gcmodule.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2022-01-13 19:12:50 (GMT)
committerGitHub <noreply@github.com>2022-01-13 19:12:50 (GMT)
commit52937c26adc35350ca0402070160cf6dc838f359 (patch)
tree173b93b382257ca8b6317b817591b88f6ed186ae /Modules/gcmodule.c
parent4ddd5da2691bea39e36debbc7f53c7cc4f13904e (diff)
downloadcpython-52937c26adc35350ca0402070160cf6dc838f359.zip
cpython-52937c26adc35350ca0402070160cf6dc838f359.tar.gz
cpython-52937c26adc35350ca0402070160cf6dc838f359.tar.bz2
bpo-46070: _PyGC_Fini() untracks objects (GH-30577) (GH-30580)
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 1a4d1c1c9b08e75e88aeac90901920938f649832)
Diffstat (limited to 'Modules/gcmodule.c')
-rw-r--r--Modules/gcmodule.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 2c6ef92..3cf1a00 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -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 */