From e77bcb0fdd0bc622213c33ad7094d28737fe51e7 Mon Sep 17 00:00:00 2001 From: Enric Tejedor Saavedra Date: Wed, 28 Sep 2022 14:20:46 +0200 Subject: [PATCH] [PyROOT] Fixes for garbage collection in Python 3.11 According to the list of changes in Python 3.11: https://docs.python.org/3.11/whatsnew/3.11.html types defined with the Py_TPFLAGS_HAVE_GC flag set but with no traverse function (PyTypeObject.tp_traverse) will cause an error. The above is true for a few types that are defined in cppyy. This commit removes the aforementioned flag from those type definitions with no traverse function. It also sets the right flags for the nonified object type; this fixes the teardown GC crashes observed when the internal memory management of ROOT was involved (e.g. the garbage collection of a tree that belongs to a file). --- .../pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx | 1 - .../cppyy/CPyCppyy/src/CustomPyTypes.cxx | 3 +-- .../cppyy/CPyCppyy/src/MemoryRegulator.cxx | 3 ++- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx index 73fb8099b5dd..f2eea396af1b 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx @@ -764,7 +764,6 @@ PyTypeObject CPPInstance_Type = { 0, // tp_as_buffer Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, // tp_flags (char*)"cppyy object proxy (internal)", // tp_doc 0, // tp_traverse diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CustomPyTypes.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CustomPyTypes.cxx index 97ce06daa717..ed41b1637c67 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/CustomPyTypes.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/CustomPyTypes.cxx @@ -78,8 +78,7 @@ PyTypeObject TypedefPointerToClass_Type = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (ternaryfunc)tpc_call, // tp_call 0, 0, 0, 0, - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_HAVE_GC, // tp_flags + Py_TPFLAGS_DEFAULT, // tp_flags 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 #if PY_VERSION_HEX >= 0x02030000 , 0 // tp_del diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/MemoryRegulator.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/MemoryRegulator.cxx index f9e92f9c8c1b..510d65f88a8d 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/MemoryRegulator.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/MemoryRegulator.cxx @@ -45,7 +45,7 @@ struct InitCPyCppyy_NoneType_t { ((PyVarObject&)CPyCppyy_NoneType).ob_size = 0; CPyCppyy_NoneType.tp_name = const_cast("CPyCppyy_NoneType"); - CPyCppyy_NoneType.tp_flags = Py_TPFLAGS_HAVE_RICHCOMPARE | Py_TPFLAGS_HAVE_GC; + CPyCppyy_NoneType.tp_flags = Py_TPFLAGS_HAVE_RICHCOMPARE; CPyCppyy_NoneType.tp_traverse = (traverseproc)0; CPyCppyy_NoneType.tp_clear = (inquiry)0; @@ -135,6 +135,7 @@ bool CPyCppyy::MemoryRegulator::RecursiveRemove( CPyCppyy_NoneType.tp_traverse = Py_TYPE(pyobj)->tp_traverse; CPyCppyy_NoneType.tp_clear = Py_TYPE(pyobj)->tp_clear; CPyCppyy_NoneType.tp_free = Py_TYPE(pyobj)->tp_free; + CPyCppyy_NoneType.tp_flags = Py_TYPE(pyobj)->tp_flags; } else if (CPyCppyy_NoneType.tp_traverse != Py_TYPE(pyobj)->tp_traverse) { // TODO: SystemError? std::cerr << "in CPyCppyy::MemoryRegulater, unexpected object of type: "