Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2021-08-11 10:29:26 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-08-11 10:37:38 +0300
commitf3e26c847b6ba0924cfd02641345164c54234425 (patch)
tree58d3fb165edb96b4c75fb88e569d37607b2e2377 /source/blender
parentcbc671947a3baca3da7d6c5a2980a86b7f6a7055 (diff)
PyAPI: report unreleased ID's with WITH_PYTHON_SAFETY enabled
This would have made T88033 more straightforward to track down.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/python/intern/bpy.c3
-rw-r--r--source/blender/python/intern/bpy_interface.c7
-rw-r--r--source/blender/python/intern/bpy_rna.c53
-rw-r--r--source/blender/python/intern/bpy_rna.h1
4 files changed, 38 insertions, 26 deletions
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);