Fix massive amount of memleaks on exit in BPY.
Essentially, our current code would not properly remove (dereference) its python objects matching various RNA data created during execution. Some cases are fairly trivial to understand (like the lack of handling of unregstering for our 'startup' operators and UI), other were more subtle (like unregistered PropertyGroups who would remove/free their RNA struct definition, without releasing first the potential matching python object). Co-authored-by: Campbell Barton <campbell@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/128899
This commit is contained in:
@@ -765,10 +765,6 @@ void BPy_init_modules(bContext *C)
|
||||
|
||||
PointerRNA ctx_ptr = RNA_pointer_create(nullptr, &RNA_Context, C);
|
||||
bpy_context_module = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ctx_ptr);
|
||||
/* odd that this is needed, 1 ref on creation and another for the module
|
||||
* but without we get a crash on exit */
|
||||
Py_INCREF(bpy_context_module);
|
||||
|
||||
PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
|
||||
|
||||
/* Register methods and property get/set for RNA types. */
|
||||
|
||||
@@ -577,7 +577,7 @@ void BPY_python_end(const bool do_python_exit)
|
||||
BPY_rna_props_clear_all();
|
||||
|
||||
/* Free other Python data. */
|
||||
pyrna_free_types();
|
||||
RNA_bpy_exit();
|
||||
|
||||
BPY_rna_exit();
|
||||
|
||||
|
||||
@@ -9096,26 +9096,14 @@ void pyrna_alloc_types()
|
||||
#endif /* !NDEBUG */
|
||||
}
|
||||
|
||||
void pyrna_free_types()
|
||||
void BPY_free_srna_pytype(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
void *py_ptr = RNA_struct_py_type_get(srna);
|
||||
|
||||
/* Avoid doing this lookup for every getattr. */
|
||||
PointerRNA ptr = RNA_blender_rna_pointer_create();
|
||||
prop = RNA_struct_find_property(&ptr, "structs");
|
||||
|
||||
RNA_PROP_BEGIN (&ptr, itemptr, prop) {
|
||||
StructRNA *srna = srna_from_ptr(&itemptr);
|
||||
void *py_ptr = RNA_struct_py_type_get(srna);
|
||||
|
||||
if (py_ptr) {
|
||||
#if 0 /* XXX: should be able to do this, but makes Python crash on exit. */
|
||||
bpy_class_free(py_ptr);
|
||||
#endif
|
||||
RNA_struct_py_type_set(srna, nullptr);
|
||||
}
|
||||
if (py_ptr) {
|
||||
bpy_class_free(py_ptr);
|
||||
RNA_struct_py_type_set(srna, nullptr);
|
||||
}
|
||||
RNA_PROP_END;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9255,11 +9243,13 @@ static PyObject *pyrna_register_class(PyObject * /*self*/, PyObject *py_class)
|
||||
pyrna_subtype_set_rna(py_class, srna_new);
|
||||
|
||||
/* Old srna still references us, keep the check in case registering somehow can free it. */
|
||||
if (RNA_struct_py_type_get(srna)) {
|
||||
if (PyObject *old_py_class = static_cast<PyObject *>(RNA_struct_py_type_get(srna))) {
|
||||
RNA_struct_py_type_set(srna, nullptr);
|
||||
#if 0
|
||||
/* Should be able to do this XXX since the old RNA adds a new ref. */
|
||||
Py_DECREF(py_class);
|
||||
Py_DECREF(old_py_class);
|
||||
#else
|
||||
UNUSED_VARS(old_py_class);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -232,10 +232,7 @@ int pyrna_struct_as_ptr_or_null_parse(PyObject *o, void *p);
|
||||
|
||||
void pyrna_struct_type_extend_capi(StructRNA *srna, PyMethodDef *method, PyGetSetDef *getset);
|
||||
|
||||
/* Called before stopping Python. */
|
||||
|
||||
void pyrna_alloc_types(void);
|
||||
void pyrna_free_types(void);
|
||||
|
||||
/* Primitive type conversion. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user