Browse Source

interrogate: avoid GC exceptions processing objects mid-construction

After 38692dd525525e20cd06204a646b35dd7e39902a, GC pauses occuring before
the __init__ function of the C++ backed object is called in a inheritance chain will
cause an exception during garbage collection and cause the python runtime to exit.

This can be observed by say, forcing a GC-pause in MetaInterval.__init__ before it calls CMetaInterval::__init__.
John C. Allwein 1 year ago
parent
commit
8cc62c9706
1 changed files with 4 additions and 3 deletions
  1. 4 3
      dtool/src/interrogate/interfaceMakerPythonNative.cxx

+ 4 - 3
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -3057,9 +3057,10 @@ write_module_class(ostream &out, Object *obj) {
       out << "static int Dtool_Traverse_" << ClassName << "(PyObject *self, visitproc visit, void *arg) {\n";
       out << "static int Dtool_Traverse_" << ClassName << "(PyObject *self, visitproc visit, void *arg) {\n";
       out << "  // If the only reference remaining is the one held by the Python wrapper,\n";
       out << "  // If the only reference remaining is the one held by the Python wrapper,\n";
       out << "  // report the circular reference to Python's GC, so that it can break it.\n";
       out << "  // report the circular reference to Python's GC, so that it can break it.\n";
-      out << "  " << cClassName  << " *local_this = nullptr;\n";
-      out << "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
-      out << "    return -1;\n";
+      out << "  " << cClassName  << " *local_this;\n";
+      out << "  DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void**)(&local_this));\n";
+      out << "  if (local_this == nullptr) {\n";
+      out << "    return 0;\n";
       out << "  }\n";
       out << "  }\n";
       out << "  if (local_this->get_ref_count() == (int)((Dtool_PyInstDef *)self)->_memory_rules) {\n";
       out << "  if (local_this->get_ref_count() == (int)((Dtool_PyInstDef *)self)->_memory_rules) {\n";
       if (py_subclassable) {
       if (py_subclassable) {