]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-111777: Fix assertion errors on incorrectly still-tracked GC object destruction...
authorT. Wouters <thomas@python.org>
Sun, 12 Nov 2023 00:03:34 +0000 (01:03 +0100)
committerGitHub <noreply@github.com>
Sun, 12 Nov 2023 00:03:34 +0000 (01:03 +0100)
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.

Modules/gcmodule.c

index 3505b085f065d0da4e1cbfb513375cc0523778e0..568e02a4210a2b22effcd6100bdae58af7d94ac9 100644 (file)
@@ -2396,14 +2396,16 @@ 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 = PyErr_GetRaisedException();
         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);
         }
+        PyErr_SetRaisedException(exc);
 #endif
-        gc_list_remove(g);
     }
     GCState *gcstate = get_gc_state();
     if (gcstate->generations[0].count > 0) {