[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [35276] trunk/blender/source/blender: Py/ RNA API test code to prevent crashing blender when python references freed ID 's.

Campbell Barton ideasman42 at gmail.com
Tue Mar 1 10:02:55 CET 2011


Revision: 35276
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=35276
Author:   campbellbarton
Date:     2011-03-01 09:02:54 +0000 (Tue, 01 Mar 2011)
Log Message:
-----------
Py/RNA API test code to prevent crashing blender when python references freed ID's.

This uses pythons GC so its no overhead during runtime but makes removing ID's slower.

Commented definition 'USE_PYRNA_INVALIDATE_GC' for now, so no functional change.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/library.c
    trunk/blender/source/blender/python/BPY_extern.h
    trunk/blender/source/blender/python/intern/bpy_rna.c
    trunk/blender/source/blender/python/intern/bpy_rna.h

Modified: trunk/blender/source/blender/blenkernel/intern/library.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/library.c	2011-03-01 08:28:37 UTC (rev 35275)
+++ trunk/blender/source/blender/blenkernel/intern/library.c	2011-03-01 09:02:54 UTC (rev 35276)
@@ -109,6 +109,10 @@
 #include "BKE_gpencil.h"
 #include "BKE_fcurve.h"
 
+#ifdef WITH_PYTHON
+#include "BPY_extern.h"
+#endif
+
 #define MAX_IDPUP		60	/* was 24 */
 
 /* GS reads the memory pointed at in a specific ordering. 
@@ -721,7 +725,11 @@
 void free_libblock(ListBase *lb, void *idv)
 {
 	ID *id= idv;
-	
+
+#ifdef WITH_PYTHON
+	BPY_id_release(id);
+#endif
+
 	switch( GS(id->name) ) {	/* GetShort from util.h */
 		case ID_SCE:
 			free_scene((Scene *)id);

Modified: trunk/blender/source/blender/python/BPY_extern.h
===================================================================
--- trunk/blender/source/blender/python/BPY_extern.h	2011-03-01 08:28:37 UTC (rev 35275)
+++ trunk/blender/source/blender/python/BPY_extern.h	2011-03-01 09:02:54 UTC (rev 35276)
@@ -93,6 +93,8 @@
 int		BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result);
 void	BPY_context_set(struct bContext *C);
 
+void	BPY_id_release(struct ID *id);
+
 #ifdef __cplusplus
 }				/* extern "C" */
 #endif

Modified: trunk/blender/source/blender/python/intern/bpy_rna.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_rna.c	2011-03-01 08:28:37 UTC (rev 35275)
+++ trunk/blender/source/blender/python/intern/bpy_rna.c	2011-03-01 09:02:54 UTC (rev 35276)
@@ -94,18 +94,55 @@
 	return -1;
 }
 
-/*
-static void pyrna_struct_invalidate(BPy_StructRNA *self)
+static void pyrna_invalidate(BPy_DummyPointerRNA *self)
 {
-	self->ptr.type= NULL;
+	self->ptr.type= NULL; /* this is checked for validity */
+	self->ptr.id.data= NULL; /* should not be needed but prevent bad pointer access, just incase */
 }
 
-static void pyrna_prop_invalidate(BPy_PropertyRNA *self)
+#ifdef USE_PYRNA_INVALIDATE_GC
+#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1))
+
+/* only for sizeof() */
+struct gc_generation {
+	PyGC_Head head;
+	int threshold;
+	int count;
+} gc_generation;
+
+static void id_release_gc(struct ID *id)
 {
-	self->ptr.type= NULL;
+	unsigned int j;
+	// unsigned int i= 0;
+	for(j=0; j<3; j++) {
+		/* hack below to get the 2 other lists from _PyGC_generation0 that are normally not exposed */
+		PyGC_Head *gen= (PyGC_Head *)(((char *)_PyGC_generation0) + (sizeof(gc_generation) * j));
+		PyGC_Head *g = gen->gc.gc_next;
+		while ((g= g->gc.gc_next) != gen) {
+			PyObject *ob= FROM_GC(g);
+			if(PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) {
+				BPy_DummyPointerRNA *ob_ptr= (BPy_DummyPointerRNA *)ob;
+				if(ob_ptr->ptr.id.data == id) {
+					pyrna_invalidate(ob_ptr);
+					// printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name);
+					// i++;
+				}
+			}
+		}
+	}
+	// printf("id_release_gc freed '%s': %d\n", id->name, i);
 }
-*/
+#endif
 
+
+void BPY_id_release(struct ID *id)
+{
+	(void)id;
+#ifdef USE_PYRNA_INVALIDATE_GC
+	id_release_gc(id);
+#endif
+}
+
 #ifdef USE_PEDANTIC_WRITE
 static short rna_disallow_writes= FALSE;
 

Modified: trunk/blender/source/blender/python/intern/bpy_rna.h
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_rna.h	2011-03-01 08:28:37 UTC (rev 35275)
+++ trunk/blender/source/blender/python/intern/bpy_rna.h	2011-03-01 09:02:54 UTC (rev 35276)
@@ -44,6 +44,9 @@
 #define BPy_PropertyRNA_Check(v)		(PyObject_TypeCheck(v, &pyrna_prop_Type))
 #define BPy_PropertyRNA_CheckExact(v)	(Py_TYPE(v) == &pyrna_prop_Type)
 
+/* method to invalidate removed py data, XXX, slow to remove objects, otherwise no overhead */
+// #define USE_PYRNA_INVALIDATE_GC
+
 /* play it safe and keep optional for now, need to test further now this affects looping on 10000's of verts for eg. */
 // #define USE_WEAKREFS
 




More information about the Bf-blender-cvs mailing list