@@ -1944,6 +1944,13 @@ _PyGC_DumpShutdownStats(PyInterpreterState *interp)
1944
1944
}
1945
1945
}
1946
1946
1947
+ static void
1948
+ finalize_unlink_gc_head (PyGC_Head * gc ) {
1949
+ PyGC_Head * prev = GC_PREV (gc );
1950
+ PyGC_Head * next = GC_NEXT (gc );
1951
+ _PyGCHead_SET_NEXT (prev , next );
1952
+ _PyGCHead_SET_PREV (next , prev );
1953
+ }
1947
1954
1948
1955
void
1949
1956
_PyGC_Fini (PyInterpreterState * interp )
@@ -1952,9 +1959,25 @@ _PyGC_Fini(PyInterpreterState *interp)
1952
1959
Py_CLEAR (gcstate -> garbage );
1953
1960
Py_CLEAR (gcstate -> callbacks );
1954
1961
1955
- /* We expect that none of this interpreters objects are shared
1956
- with other interpreters.
1957
- See https://github.com/python/cpython/issues/90228. */
1962
+ /* Prevent a subtle bug that affects sub-interpreters that use basic
1963
+ * single-phase init extensions (m_size == -1). Those extensions cause objects
1964
+ * to be shared between interpreters, via the PyDict_Update(mdict, m_copy) call
1965
+ * in import_find_extension().
1966
+ *
1967
+ * If they are GC objects, their GC head next or prev links could refer to
1968
+ * the interpreter _gc_runtime_state PyGC_Head nodes. Those nodes go away
1969
+ * when the interpreter structure is freed and so pointers to them become
1970
+ * invalid. If those objects are still used by another interpreter and
1971
+ * UNTRACK is called on them, a crash will happen. We untrack the nodes
1972
+ * here to avoid that.
1973
+ *
1974
+ * This bug was originally fixed when reported as gh-90228. The bug was
1975
+ * re-introduced in gh-94673.
1976
+ */
1977
+ finalize_unlink_gc_head (& gcstate -> young .head );
1978
+ finalize_unlink_gc_head (& gcstate -> old [0 ].head );
1979
+ finalize_unlink_gc_head (& gcstate -> old [1 ].head );
1980
+ finalize_unlink_gc_head (& gcstate -> permanent_generation .head );
1958
1981
}
1959
1982
1960
1983
/* for debugging */
0 commit comments