Skip to content

Commit 69fd1f2

Browse files
authored
[3.12] gh-116510: Fix crash during sub-interpreter shutdown (gh-124536)
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.
1 parent c6f3f83 commit 69fd1f2

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a bug that can cause a crash when sub-interpreters use "basic"
2+
single-phase extension modules. Shared objects could refer to PyGC_Head
3+
nodes that had been freed as part of interpreter cleanup.

Modules/gcmodule.c

+26-3
Original file line numberDiff line numberDiff line change
@@ -2174,6 +2174,13 @@ _PyGC_DumpShutdownStats(PyInterpreterState *interp)
21742174
}
21752175
}
21762176

2177+
static void
2178+
finalize_unlink_gc_head(PyGC_Head *gc) {
2179+
PyGC_Head *prev = GC_PREV(gc);
2180+
PyGC_Head *next = GC_NEXT(gc);
2181+
_PyGCHead_SET_NEXT(prev, next);
2182+
_PyGCHead_SET_PREV(next, prev);
2183+
}
21772184

21782185
void
21792186
_PyGC_Fini(PyInterpreterState *interp)
@@ -2182,9 +2189,25 @@ _PyGC_Fini(PyInterpreterState *interp)
21822189
Py_CLEAR(gcstate->garbage);
21832190
Py_CLEAR(gcstate->callbacks);
21842191

2185-
/* We expect that none of this interpreters objects are shared
2186-
with other interpreters.
2187-
See https://github.com/python/cpython/issues/90228. */
2192+
/* Prevent a subtle bug that affects sub-interpreters that use basic
2193+
* single-phase init extensions (m_size == -1). Those extensions cause objects
2194+
* to be shared between interpreters, via the PyDict_Update(mdict, m_copy) call
2195+
* in import_find_extension().
2196+
*
2197+
* If they are GC objects, their GC head next or prev links could refer to
2198+
* the interpreter _gc_runtime_state PyGC_Head nodes. Those nodes go away
2199+
* when the interpreter structure is freed and so pointers to them become
2200+
* invalid. If those objects are still used by another interpreter and
2201+
* UNTRACK is called on them, a crash will happen. We untrack the nodes
2202+
* here to avoid that.
2203+
*
2204+
* This bug was originally fixed when reported as gh-90228. The bug was
2205+
* re-introduced in gh-94673.
2206+
*/
2207+
for (int i = 0; i < NUM_GENERATIONS; i++) {
2208+
finalize_unlink_gc_head(&gcstate->generations[i].head);
2209+
}
2210+
finalize_unlink_gc_head(&gcstate->permanent_generation.head);
21882211
}
21892212

21902213
/* for debugging */

0 commit comments

Comments
 (0)