]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-130382: add missing `_PyReftracerTrack` to ceval `Py_DECREF` (#130689)
authorTomasz Pytel <tompytel@gmail.com>
Thu, 13 Mar 2025 16:31:49 +0000 (12:31 -0400)
committerGitHub <noreply@github.com>
Thu, 13 Mar 2025 16:31:49 +0000 (12:31 -0400)
Lib/test/test_capi/test_misc.py
Misc/NEWS.d/next/Core_and_Builtins/2025-02-28-16-13-02.gh-issue-130382.66VTmy.rst [new file with mode: 0644]
Modules/_testcapimodule.c
Python/ceval.c

index 6c4cf5bd6598bcdba082dedd4e0771c30a7c859e..2e1e8e77d620d131f35b6f62278639dae22722a3 100644 (file)
@@ -2884,5 +2884,22 @@ class TestVersions(unittest.TestCase):
                 self.assertEqual(result, expected)
 
 
+class TestCEval(unittest.TestCase):
+   def test_ceval_decref(self):
+        code = textwrap.dedent("""
+            import _testcapi
+            _testcapi.toggle_reftrace_printer(True)
+            l1 = []
+            l2 = []
+            del l1
+            del l2
+            _testcapi.toggle_reftrace_printer(False)
+        """)
+        _, out, _ = assert_python_ok("-c", code)
+        lines = out.decode("utf-8").splitlines()
+        self.assertEqual(lines.count("CREATE list"), 2)
+        self.assertEqual(lines.count("DESTROY list"), 2)
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-28-16-13-02.gh-issue-130382.66VTmy.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-28-16-13-02.gh-issue-130382.66VTmy.rst
new file mode 100644 (file)
index 0000000..8b775c8
--- /dev/null
@@ -0,0 +1 @@
+Fix ``PyRefTracer_DESTROY`` not being sent from :file:`Python/ceval.c` ``Py_DECREF()``.
index 9260c7659440ea78277b4d664d9ed1065ef9ceee..409dd02e1435b580d517d9143c0e671889f99095 100644 (file)
@@ -2515,6 +2515,31 @@ code_offset_to_line(PyObject* self, PyObject* const* args, Py_ssize_t nargsf)
 }
 
 
+static int
+_reftrace_printer(PyObject *obj, PyRefTracerEvent event, void *counter_data)
+{
+    if (event == PyRefTracer_CREATE) {
+        printf("CREATE %s\n", Py_TYPE(obj)->tp_name);
+    }
+    else {  // PyRefTracer_DESTROY
+        printf("DESTROY %s\n", Py_TYPE(obj)->tp_name);
+    }
+    return 0;
+}
+
+// A simple reftrace printer for very simple tests
+static PyObject *
+toggle_reftrace_printer(PyObject *ob, PyObject *arg)
+{
+    if (arg == Py_True) {
+        PyRefTracer_SetTracer(_reftrace_printer, NULL);
+    }
+    else {
+        PyRefTracer_SetTracer(NULL, NULL);
+    }
+    Py_RETURN_NONE;
+}
+
 static PyMethodDef TestMethods[] = {
     {"set_errno",               set_errno,                       METH_VARARGS},
     {"test_config",             test_config,                     METH_NOARGS},
@@ -2608,6 +2633,7 @@ static PyMethodDef TestMethods[] = {
     {"finalize_thread_hang", finalize_thread_hang, METH_O, NULL},
     {"test_atexit", test_atexit, METH_NOARGS},
     {"code_offset_to_line", _PyCFunction_CAST(code_offset_to_line), METH_FASTCALL},
+    {"toggle_reftrace_printer", toggle_reftrace_printer, METH_O},
     {NULL, NULL} /* sentinel */
 };
 
index f9089d7f11f280f46d8ebedf78189ed750b96000..34f4417f5fc4871a19f11aab5a35155a57ee0e1b 100644 (file)
@@ -80,6 +80,7 @@
         } \
         _Py_DECREF_STAT_INC(); \
         if (--op->ob_refcnt == 0) { \
+            _PyReftracerTrack(op, PyRefTracer_DESTROY); \
             destructor dealloc = Py_TYPE(op)->tp_dealloc; \
             (*dealloc)(op); \
         } \