diff options
-rw-r--r-- | source/blender/blenkernel/intern/unit.c | 34 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_define.c | 7 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_render.c | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_ui.c | 9 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 8 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 64 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_init_exit.c | 20 |
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(); |