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>2009-08-14 16:29:55 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-08-14 16:29:55 +0400
commit08f0938434598b23d0dd1879f598e342a194cb63 (patch)
tree24534061675641b9efab5e69508ac9bde30b5efa
parent4bbccd39bc827e5d794bdbe987b4d48164e8d950 (diff)
- registering new python classes runs the free functions on existing classes.
- print an error if RNA Structs are freed with a python pointer set to help with debugging leaks. - fix for unlikely eternal loop in unit conversion.
-rw-r--r--source/blender/blenkernel/intern/unit.c34
-rw-r--r--source/blender/makesrna/intern/rna_define.c7
-rw-r--r--source/blender/makesrna/intern/rna_render.c3
-rw-r--r--source/blender/makesrna/intern/rna_ui.c9
-rw-r--r--source/blender/python/intern/bpy_interface.c8
-rw-r--r--source/blender/python/intern/bpy_rna.c64
-rw-r--r--source/blender/python/intern/bpy_rna.h3
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c20
8 files changed, 118 insertions, 30 deletions
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index ba609fc5611..140f155abc3 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -294,9 +294,9 @@ static char *unit_find_str(char *str, char *substr)
static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit, char *replace_str)
{
- char *str_found= unit_find_str(str, replace_str);
+ char *str_found;
- if(str_found) { /* XXX - investigate, does not respect len_max properly */
+ if((len_max>0) && (str_found= unit_find_str(str, replace_str))) { /* XXX - investigate, does not respect len_max properly */
int len, len_num, len_name, len_move, found_ofs;
found_ofs = (int)(str_found-str);
@@ -330,20 +330,22 @@ static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pr
memcpy(str_found, str_tmp, len_num); /* without the string terminator */
}
- str[len_max-1]= '\0'; /* since the null terminator wont be moved */
- return 1;
+ /* since the null terminator wont be moved if the stringlen_max
+ * was not long enough to fit everything in it */
+ str[len_max-1]= '\0';
+ return found_ofs + len_num;
}
return 0;
}
static int unit_replace(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit)
{
- int change= 0;
- change |= unit_scale_str(str, len_max, str_tmp, scale_pref, unit, unit->name_short);
- change |= unit_scale_str(str, len_max, str_tmp, scale_pref, unit, unit->name_plural);
- change |= unit_scale_str(str, len_max, str_tmp, scale_pref, unit, unit->name_alt);
- change |= unit_scale_str(str, len_max, str_tmp, scale_pref, unit, unit->name);
- return change;
+ int ofs= 0;
+ ofs += unit_scale_str(str+ofs, len_max-ofs, str_tmp, scale_pref, unit, unit->name_short);
+ ofs += unit_scale_str(str+ofs, len_max-ofs, str_tmp, scale_pref, unit, unit->name_plural);
+ ofs += unit_scale_str(str+ofs, len_max-ofs, str_tmp, scale_pref, unit, unit->name_alt);
+ ofs += unit_scale_str(str+ofs, len_max-ofs, str_tmp, scale_pref, unit, unit->name);
+ return ofs;
}
static int unit_find(char *str, bUnitDef *unit)
@@ -401,12 +403,12 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre
usys_iter= unit_get_system(system_iter, type);
for(unit= usys_iter->units; unit->name; unit++) {
- if(unit->flag & B_UNIT_DEF_SUPPRESS)
- continue;
-
- /* incase there are multiple instances */
- while(unit_replace(str, len_max, str_tmp, scale_pref, unit))
- change= 1;
+ if((unit->flag & B_UNIT_DEF_SUPPRESS) == 0) {
+ int ofs = 0;
+ /* incase there are multiple instances */
+ while((ofs=unit_replace(str+ofs, len_max-ofs, str_tmp, scale_pref, unit)))
+ change= 1;
+ }
}
}
}
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 5f1a069d876..ffbacdee69f 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -465,6 +465,12 @@ void RNA_struct_free(BlenderRNA *brna, StructRNA *srna)
PropertyRNA *prop, *nextprop;
PropertyRNA *parm, *nextparm;
+ if(srna->flag & STRUCT_RUNTIME) {
+ if(RNA_struct_py_type_get(srna)) {
+ fprintf(stderr, "StructRNA \"%s\" freed while holdng a python reference\n", srna->name);
+ }
+ }
+
for(prop=srna->cont.properties.first; prop; prop=nextprop) {
nextprop= prop->next;
@@ -496,6 +502,7 @@ void RNA_struct_free(BlenderRNA *brna, StructRNA *srna)
if(srna->flag & STRUCT_RUNTIME)
rna_freelinkN(&brna->structs, srna);
+
#endif
}
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 7268d560282..040284cb07b 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -106,6 +106,9 @@ static void rna_RenderEngine_unregister(const bContext *C, StructRNA *type)
if(!et)
return;
+ et->ext.free(et->ext.data); /* decref's the PyObject that the srna owns */
+ RNA_struct_py_type_set(type, NULL); /* NULL the srna's value so RNA_struct_free wont complain of a leak */
+
BLI_freelinkN(&R_engines, et);
RNA_struct_free(&BLENDER_RNA, type);
}
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 590f85fedd7..5a33bcd6374 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -138,6 +138,9 @@ static void rna_Panel_unregister(const bContext *C, StructRNA *type)
if(!(art=region_type_find(NULL, pt->space_type, pt->region_type)))
return;
+ pt->ext.free(pt->ext.data); /* decref's the PyObject that the srna owns */
+ RNA_struct_py_type_set(type, NULL); /* NULL the srna's value so RNA_struct_free wont complain of a leak */
+
BLI_freelinkN(&art->paneltypes, pt);
RNA_struct_free(&BLENDER_RNA, type);
@@ -233,6 +236,9 @@ static void rna_Header_unregister(const bContext *C, StructRNA *type)
if(!(art=region_type_find(NULL, ht->space_type, RGN_TYPE_HEADER)))
return;
+ ht->ext.free(ht->ext.data); /* decref's the PyObject that the srna owns */
+ RNA_struct_py_type_set(type, NULL); /* NULL the srna's value so RNA_struct_free wont complain of a leak */
+
BLI_freelinkN(&art->headertypes, ht);
RNA_struct_free(&BLENDER_RNA, type);
@@ -347,6 +353,9 @@ static void rna_Menu_unregister(const bContext *C, StructRNA *type)
if(!(art=region_type_find(NULL, mt->space_type, RGN_TYPE_HEADER)))
return;
+ mt->ext.free(mt->ext.data); /* decref's the PyObject that the srna owns */
+ RNA_struct_py_type_set(type, NULL); /* NULL the srna's value so RNA_struct_free wont complain of a leak */
+
BLI_freelinkN(&art->menutypes, mt);
RNA_struct_free(&BLENDER_RNA, type);
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index eedbe3b224f..ca5f933de80 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -270,10 +270,14 @@ void BPY_start_python( int argc, char **argv )
void BPY_end_python( void )
{
+ fprintf(stderr, "Ending Python!\n");
+
PyGILState_Ensure(); /* finalizing, no need to grab the state */
// free other python data.
- //BPY_rna_free_types();
+ pyrna_free_types();
+
+ /* clear all python data from structs */
Py_Finalize( );
@@ -292,6 +296,8 @@ void BPY_end_python( void )
printf("\n");
+ fprintf(stderr, "Ending Python Done!\n");
+
#endif
}
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 0c03b439e78..c71d7c7d90d 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -2319,17 +2319,22 @@ PyObject* pyrna_srna_Subtype(StructRNA *srna)
if(base && base != srna) {
/*/printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna); */
py_base= pyrna_srna_Subtype(base);
+ Py_DECREF(py_base); /* srna owns, this is only to pass as an arg */
}
if(py_base==NULL) {
py_base= (PyObject *)&pyrna_struct_Type;
- Py_INCREF(py_base);
}
- newclass = PyObject_CallFunction( (PyObject*)&PyType_Type, "s(N){ssss}", idname, py_base, "__module__","bpy.types", "__doc__",descr);
+ /* always use O not N when calling, N causes refcount errors */
+ newclass = PyObject_CallFunction( (PyObject*)&PyType_Type, "s(O){ssss}", idname, py_base, "__module__","bpy.types", "__doc__",descr);
if (newclass) {
+
+ /* incref's the new class (has 2 now)
+ * srna owns one, and the other is owned by the caller */
pyrna_subtype_set_rna(newclass, srna);
+
// PyObSpit("NewStructRNA Type: ", (PyObject *)newclass);
/* attach functions into the class
@@ -2353,9 +2358,21 @@ PyObject* pyrna_srna_Subtype(StructRNA *srna)
return newclass;
}
+/* use for subtyping so we know which srna is used for a PointerRNA */
+static StructRNA *srna_from_ptr(PointerRNA *ptr)
+{
+ if(ptr->type == &RNA_Struct) {
+ return ptr->data;
+ }
+ else {
+ return ptr->type;
+ }
+}
+
+/* always returns a new ref, be sure to decref when done */
PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
{
- return pyrna_srna_Subtype((ptr->type == &RNA_Struct) ? ptr->data : ptr->type);
+ return pyrna_srna_Subtype(srna_from_ptr(ptr));
}
/*-----------------------CreatePyObject---------------------------------*/
@@ -2371,7 +2388,7 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
if (tp) {
pyrna = (BPy_StructRNA *) tp->tp_alloc(tp, 0);
- Py_DECREF(tp);
+ Py_DECREF(tp); /* srna owns, cant hold a ref */
}
else {
fprintf(stderr, "Could not make type\n");
@@ -2970,11 +2987,46 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
static void bpy_class_free(void *pyob_ptr)
{
+ PyObject *self= (PyObject *)pyob_ptr;
+ PyGILState_STATE gilstate;
+
+ gilstate = PyGILState_Ensure();
+
+ PyDict_Clear(((PyTypeObject*)self)->tp_dict);
+
if(G.f&G_DEBUG) {
- if(((PyObject *)pyob_ptr)->ob_refcnt > 1)
- PyObSpit("zombie class - ref should be 1", (PyObject *)pyob_ptr);
+ if(self->ob_refcnt > 1) {
+ PyObSpit("zombie class - ref should be 1", self);
+ }
}
+
Py_DECREF((PyObject *)pyob_ptr);
+
+ PyGILState_Release(gilstate);
+}
+
+void pyrna_free_types(void)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* avoid doing this lookup for every getattr */
+ RNA_blender_rna_pointer_create(&ptr);
+ 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, NULL);
+ }
+ }
+ RNA_PROP_END;
}
PyObject *pyrna_basetype_register(PyObject *self, PyObject *args)
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index 9138fd511b0..d14b7f1addb 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -83,4 +83,7 @@ PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *pyrna_basetype_register(PyObject *self, PyObject *args);
PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *args);
+/* called before stopping python */
+void pyrna_free_types(void);
+
#endif
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 57e028670e7..c679cbcab53 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -208,12 +208,6 @@ void WM_exit(bContext *C)
BKE_freecubetable();
- /* before free_blender so py's gc happens while library still exists */
- /* needed at least for a rare sigsegv that can happen in pydrivers */
-#ifndef DISABLE_PYTHON
- BPY_end_python();
-#endif
-
fastshade_free_render(); /* shaded view */
ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */
wm_free_reports(C); /* before free_blender! - since the ListBases get freed there */
@@ -233,6 +227,18 @@ void WM_exit(bContext *C)
// free_txt_data();
+
+#ifndef DISABLE_PYTHON
+ /* XXX - old note */
+ /* before free_blender so py's gc happens while library still exists */
+ /* needed at least for a rare sigsegv that can happen in pydrivers */
+
+ /* Update for blender 2.5, move after free_blender because blender now holds references to PyObject's
+ * so decref'ing them after python ends causes bad problems every time
+ * the pyDriver bug can be fixed if it happens again we can deal with it then */
+ BPY_end_python();
+#endif
+
libtiff_exit();
#ifdef WITH_QUICKTIME
@@ -256,7 +262,7 @@ void WM_exit(bContext *C)
UI_exit();
BKE_userdef_free();
- RNA_exit();
+ RNA_exit(); /* should be after BPY_end_python so struct python slots are cleared */
wm_ghost_exit();