Revision: 22451
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=22451
Author:   campbellbarton
Date:     2009-08-14 14:29:55 +0200 (Fri, 14 Aug 2009)

Log Message:
-----------
- 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.

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/blenkernel/intern/unit.c
    branches/blender2.5/blender/source/blender/makesrna/intern/rna_define.c
    branches/blender2.5/blender/source/blender/makesrna/intern/rna_render.c
    branches/blender2.5/blender/source/blender/makesrna/intern/rna_ui.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_rna.h
    
branches/blender2.5/blender/source/blender/windowmanager/intern/wm_init_exit.c

Modified: branches/blender2.5/blender/source/blender/blenkernel/intern/unit.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/intern/unit.c 
2009-08-14 11:09:19 UTC (rev 22450)
+++ branches/blender2.5/blender/source/blender/blenkernel/intern/unit.c 
2009-08-14 12:29:55 UTC (rev 22451)
@@ -294,9 +294,9 @@
 
 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 @@
                        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 @@
                                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;
+                                       }
                                }
                        }
                }

Modified: 
branches/blender2.5/blender/source/blender/makesrna/intern/rna_define.c
===================================================================
--- branches/blender2.5/blender/source/blender/makesrna/intern/rna_define.c     
2009-08-14 11:09:19 UTC (rev 22450)
+++ branches/blender2.5/blender/source/blender/makesrna/intern/rna_define.c     
2009-08-14 12:29:55 UTC (rev 22451)
@@ -465,6 +465,12 @@
        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 @@
 
        if(srna->flag & STRUCT_RUNTIME)
                rna_freelinkN(&brna->structs, srna);
+
 #endif
 }
 

Modified: 
branches/blender2.5/blender/source/blender/makesrna/intern/rna_render.c
===================================================================
--- branches/blender2.5/blender/source/blender/makesrna/intern/rna_render.c     
2009-08-14 11:09:19 UTC (rev 22450)
+++ branches/blender2.5/blender/source/blender/makesrna/intern/rna_render.c     
2009-08-14 12:29:55 UTC (rev 22451)
@@ -106,6 +106,9 @@
        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);
 }

Modified: branches/blender2.5/blender/source/blender/makesrna/intern/rna_ui.c
===================================================================
--- branches/blender2.5/blender/source/blender/makesrna/intern/rna_ui.c 
2009-08-14 11:09:19 UTC (rev 22450)
+++ branches/blender2.5/blender/source/blender/makesrna/intern/rna_ui.c 
2009-08-14 12:29:55 UTC (rev 22451)
@@ -138,6 +138,9 @@
        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 @@
        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 @@
        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);
 

Modified: 
branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c    
2009-08-14 11:09:19 UTC (rev 22450)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c    
2009-08-14 12:29:55 UTC (rev 22451)
@@ -270,10 +270,14 @@
 
 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 @@
 
        printf("\n");
 
+       fprintf(stderr, "Ending Python Done!\n");
+
 #endif
 
 }

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c  
2009-08-14 11:09:19 UTC (rev 22450)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c  
2009-08-14 12:29:55 UTC (rev 22451)
@@ -2319,17 +2319,22 @@
                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 @@
        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 @@
                
                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,13 +2987,48 @@
 
 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)
 {
        bContext *C= NULL;

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_rna.h
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_rna.h  
2009-08-14 11:09:19 UTC (rev 22450)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_rna.h  
2009-08-14 12:29:55 UTC (rev 22451)
@@ -83,4 +83,7 @@
 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 output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to