[3.11] gh-111777: Fix assertion errors on incorrectly still-tracked GC object destruction (GH-111778) (GH-111990)

In PyObject_GC_Del, in Py_DEBUG mode, when warning about GC objects that
were not properly untracked before starting destruction, take care to
untrack the object _before_ warning, to avoid triggering a GC run and
causing the problem the code tries to warn about. Also make sure to save and
restore any pending exceptions, which the warning would otherwise clobber or
trigger an assertion error on.
(cherry picked from commit ce6a533c4b)

Co-authored-by: T. Wouters <thomas@python.org>
This commit is contained in:
Miss Islington (bot) 2024-01-17 15:10:12 +01:00 committed by GitHub
parent 99a7bdc646
commit 67424458d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 5 additions and 1 deletions

View File

@ -2347,14 +2347,18 @@ PyObject_GC_Del(void *op)
size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type);
PyGC_Head *g = AS_GC(op);
if (_PyObject_GC_IS_TRACKED(op)) {
gc_list_remove(g);
#ifdef Py_DEBUG
PyObject *exc, *exc_value, *exc_tb;
PyErr_Fetch(&exc, &exc_value, &exc_tb);
if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0,
"gc", NULL, "Object of type %s is not untracked before destruction",
((PyObject*)op)->ob_type->tp_name)) {
PyErr_WriteUnraisable(NULL);
}
if (exc != NULL)
PyErr_Restore(exc, exc_value, exc_tb);
#endif
gc_list_remove(g);
}
GCState *gcstate = get_gc_state();
if (gcstate->generations[0].count > 0) {