[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [22451] branches/blender2.5/blender/source /blender: - registering new python classes runs the free functions on existing classes .

Campbell Barton ideasman42 at gmail.com
Fri Aug 14 14:29:56 CEST 2009


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. @@




More information about the Bf-blender-cvs mailing list