summaryrefslogtreecommitdiffstats
path: root/Python/gc.c
diff options
context:
space:
mode:
authorNeil Schemenauer <nas-github@arctrix.com>2024-09-27 02:33:07 (GMT)
committerGitHub <noreply@github.com>2024-09-27 02:33:07 (GMT)
commit6f9525dd3f0ef5809106ca0923a7512d666a04bb (patch)
tree88edd0ab74571083573563e7abdd2b4a51c2d379 /Python/gc.c
parent98b2ed7e239c807f379cd2bf864f372d79064aac (diff)
downloadcpython-6f9525dd3f0ef5809106ca0923a7512d666a04bb.zip
cpython-6f9525dd3f0ef5809106ca0923a7512d666a04bb.tar.gz
cpython-6f9525dd3f0ef5809106ca0923a7512d666a04bb.tar.bz2
gh-116510: Fix crash during sub-interpreter shutdown (gh-124645)
Fix a bug that can cause a crash when sub-interpreters use "basic" single-phase extension modules. Shared objects could refer to PyGC_Head nodes that had been freed as part of interpreter shutdown.
Diffstat (limited to 'Python/gc.c')
-rw-r--r--Python/gc.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/Python/gc.c b/Python/gc.c
index 024d041..028657e 100644
--- a/Python/gc.c
+++ b/Python/gc.c
@@ -1944,6 +1944,13 @@ _PyGC_DumpShutdownStats(PyInterpreterState *interp)
}
}
+static void
+finalize_unlink_gc_head(PyGC_Head *gc) {
+ PyGC_Head *prev = GC_PREV(gc);
+ PyGC_Head *next = GC_NEXT(gc);
+ _PyGCHead_SET_NEXT(prev, next);
+ _PyGCHead_SET_PREV(next, prev);
+}
void
_PyGC_Fini(PyInterpreterState *interp)
@@ -1952,9 +1959,25 @@ _PyGC_Fini(PyInterpreterState *interp)
Py_CLEAR(gcstate->garbage);
Py_CLEAR(gcstate->callbacks);
- /* We expect that none of this interpreters objects are shared
- with other interpreters.
- See https://github.com/python/cpython/issues/90228. */
+ /* Prevent a subtle bug that affects sub-interpreters that use basic
+ * single-phase init extensions (m_size == -1). Those extensions cause objects
+ * to be shared between interpreters, via the PyDict_Update(mdict, m_copy) call
+ * in import_find_extension().
+ *
+ * If they are GC objects, their GC head next or prev links could refer to
+ * the interpreter _gc_runtime_state PyGC_Head nodes. Those nodes go away
+ * when the interpreter structure is freed and so pointers to them become
+ * invalid. If those objects are still used by another interpreter and
+ * UNTRACK is called on them, a crash will happen. We untrack the nodes
+ * here to avoid that.
+ *
+ * This bug was originally fixed when reported as gh-90228. The bug was
+ * re-introduced in gh-94673.
+ */
+ finalize_unlink_gc_head(&gcstate->young.head);
+ finalize_unlink_gc_head(&gcstate->old[0].head);
+ finalize_unlink_gc_head(&gcstate->old[1].head);
+ finalize_unlink_gc_head(&gcstate->permanent_generation.head);
}
/* for debugging */