]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46070: _PyGC_Fini() untracks objects (GH-30577)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 13 Jan 2022 18:50:09 +0000 (10:50 -0800)
committerGitHub <noreply@github.com>
Thu, 13 Jan 2022 18:50:09 +0000 (10:50 -0800)
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)

Co-authored-by: Victor Stinner <vstinner@python.org>
Misc/NEWS.d/next/Core and Builtins/2022-01-13-17-58-56.bpo-46070.q8IGth.rst [new file with mode: 0644]
Modules/gcmodule.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-13-17-58-56.bpo-46070.q8IGth.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-13-17-58-56.bpo-46070.q8IGth.rst
new file mode 100644 (file)
index 0000000..4ed088f
--- /dev/null
@@ -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.
index e5e5aa3287b0d6de82672549e785ec00cd19235f..805a159d53d60fdb629ed9e4c0b00e2b9158f4b5 100644 (file)
@@ -2162,12 +2162,36 @@ _PyGC_DumpShutdownStats(PyInterpreterState *interp)
     }
 }
 
+
+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(PyInterpreterState *interp)
 {
     GCState *gcstate = &interp->gc;
     Py_CLEAR(gcstate->garbage);
     Py_CLEAR(gcstate->callbacks);
+
+    if (!_Py_IsMainInterpreter(interp)) {
+        // 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 */