diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2022-01-13 18:50:09 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-13 18:50:09 (GMT) |
commit | e6bb17fe29713368e1fd93d9ac9611017c4f570c (patch) | |
tree | 47bf5c6217a36e98bd2cef4285a6c4521a1a120b /Modules/gcmodule.c | |
parent | 3ce6945f5f434806eea700eb5ff1bed6d39395e1 (diff) | |
download | cpython-e6bb17fe29713368e1fd93d9ac9611017c4f570c.zip cpython-e6bb17fe29713368e1fd93d9ac9611017c4f570c.tar.gz cpython-e6bb17fe29713368e1fd93d9ac9611017c4f570c.tar.bz2 |
bpo-46070: _PyGC_Fini() untracks objects (GH-30577)
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>
Diffstat (limited to 'Modules/gcmodule.c')
-rw-r--r-- | Modules/gcmodule.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index e5e5aa3..805a159 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -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 */ |