[Bf-blender-cvs] [f3e26c847b6] master: PyAPI: report unreleased ID's with WITH_PYTHON_SAFETY enabled

Campbell Barton noreply at git.blender.org
Wed Aug 11 09:38:54 CEST 2021


Commit: f3e26c847b6ba0924cfd02641345164c54234425
Author: Campbell Barton
Date:   Wed Aug 11 17:29:26 2021 +1000
Branches: master
https://developer.blender.org/rBf3e26c847b6ba0924cfd02641345164c54234425

PyAPI: report unreleased ID's with WITH_PYTHON_SAFETY enabled

This would have made T88033 more straightforward to track down.

===================================================================

M	source/blender/python/intern/bpy.c
M	source/blender/python/intern/bpy_interface.c
M	source/blender/python/intern/bpy_rna.c
M	source/blender/python/intern/bpy_rna.h

===================================================================

diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 30a61067c9e..0e0f431cb19 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -417,9 +417,6 @@ void BPy_init_modules(struct bContext *C)
   PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod);
   Py_DECREF(mod);
 
-  /* run first, initializes rna types */
-  BPY_rna_init();
-
   /* needs to be first so bpy_types can run */
   PyModule_AddObject(mod, "types", BPY_rna_types());
 
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 35450e3eaad..945933dd8b7 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -502,7 +502,10 @@ void BPY_python_start(bContext *C, int argc, const char **argv)
   }
 #endif
 
-  /* bpy.* and lets us import it */
+  /* Run first, initializes RNA types. */
+  BPY_rna_init();
+
+  /* Defines `bpy.*` and lets us import it. */
   BPy_init_modules(C);
 
   pyrna_alloc_types();
@@ -541,6 +544,8 @@ void BPY_python_end(void)
   /* free other python data. */
   pyrna_free_types();
 
+  BPY_rna_exit();
+
   /* clear all python data from structs */
 
   bpy_intern_string_exit();
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index b83c13e1974..17cbf8e4569 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -181,23 +181,13 @@ static PyMethodDef id_free_weakref_cb_def = {
 /* Adds a reference to the list, remember to decref. */
 static GHash *id_weakref_pool_get(ID *id)
 {
-  GHash *weakinfo_hash = NULL;
-
-  if (id_weakref_pool) {
-    weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id);
-  }
-  else {
-    /* First time, allocate pool. */
-    id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool");
-    weakinfo_hash = NULL;
-  }
-
+  GHash *weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id);
   if (weakinfo_hash == NULL) {
-    /* We use a ghash as a set, we could use libHX's HXMAP_SINGULAR, but would be an extra dep. */
+    /* This could be a set, values are used to keep a reference back to the ID
+     * (all of them are the same). */
     weakinfo_hash = BLI_ghash_ptr_new("rna_id");
     BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash);
   }
-
   return weakinfo_hash;
 }
 
@@ -283,14 +273,6 @@ static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash)
 
   BLI_ghash_remove(id_weakref_pool, (void *)id, NULL, NULL);
   BLI_ghash_free(weakinfo_hash, NULL, NULL);
-
-  if (BLI_ghash_len(id_weakref_pool) == 0) {
-    BLI_ghash_free(id_weakref_pool, NULL, NULL);
-    id_weakref_pool = NULL;
-#  ifdef DEBUG_RNA_WEAKREF
-    printf("id_release_weakref freeing pool\n");
-#  endif
-  }
 }
 
 static void id_release_weakref(struct ID *id)
@@ -310,7 +292,8 @@ void BPY_id_release(struct ID *id)
 #endif
 
 #ifdef USE_PYRNA_INVALIDATE_WEAKREF
-  if (id_weakref_pool) {
+  /* Check for NULL since this may run before Python has been started. */
+  if (id_weakref_pool != NULL) {
     PyGILState_STATE gilstate = PyGILState_Ensure();
 
     id_release_weakref(id);
@@ -7776,6 +7759,32 @@ void BPY_rna_init(void)
     return;
   }
 #endif
+
+#ifdef USE_PYRNA_INVALIDATE_WEAKREF
+  BLI_assert(id_weakref_pool == NULL);
+  id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool");
+#endif
+}
+
+void BPY_rna_exit(void)
+{
+#ifdef USE_PYRNA_INVALIDATE_WEAKREF
+  /* This can help track down which kinds of data were not released.
+   * If they were in fact freed by Blender, printing their names
+   * will crash giving a useful error with address sanitizer. The likely cause
+   * for this list not being empty is a missing call to: #BKE_libblock_free_data_py. */
+  const int id_weakref_pool_len = BLI_ghash_len(id_weakref_pool);
+  if (id_weakref_pool_len != id_weakref_pool_len) {
+    printf("Found %d unreleased ID's\n", id_weakref_pool_len);
+    GHashIterator gh_iter;
+    GHASH_ITER (gh_iter, id_weakref_pool) {
+      ID *id = BLI_ghashIterator_getKey(&gh_iter);
+      printf("ID: %s\n", id->name);
+    }
+  }
+  BLI_ghash_free(id_weakref_pool, NULL, NULL);
+  id_weakref_pool = NULL;
+#endif
 }
 
 /* 'bpy.data' from Python. */
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index 24dbad53eb3..fd468bed470 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -181,6 +181,7 @@ StructRNA *srna_from_self(PyObject *self, const char *error_prefix);
 StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix);
 
 void BPY_rna_init(void);
+void BPY_rna_exit(void);
 PyObject *BPY_rna_module(void);
 void BPY_update_rna_module(void);
 // PyObject *BPY_rna_doc(void);



More information about the Bf-blender-cvs mailing list