[L2Ork-dev] Delayed pd_unbind

Ivica Ico Bukvic ico at vt.edu
Thu Nov 14 00:03:24 UTC 2013


So, attached is the diff of m_pd.c between version 20120607 and current 
(with Albert's additions). The old one does not crash while new one 
does. Compiling latest version with the old m_pd.c does not crash either 
so the core of the problem is apparent in the attached diff.
-------------- next part --------------
--- m_pd.c	2012-05-28 02:05:22.000000000 -0400
+++ /home/ico/Downloads/PureData/pure-data/pd/src/m_pd.c	2013-11-13 17:04:31.631095782 -0500
@@ -25,75 +25,6 @@
     if (!c) 
         bug ("pd_new: apparently called before setup routine");
 
-	/* 	here we make sure we do not create objects at the same memory address as before
-		to avoid double-entry bug that is invoked when this happens. why? no idea...
-		tcl/tk definitely sends only one command via socket, yet it is activated multiple
-		times inside c code. perhaps class_addmethod is never cleaned out (although this
-		makes no sense either as we use calloc which should zero everything out, yet even
-		that is not entirely guarranteed)
-
-		we do this by comparing the newly allocated address with preexisting list of
-		canvases that were created in the past.
-
-		if a duplicate is triggered, we deallocate memory and reallocate it assigning 
-		a random additional amount of memory and then resize allocation to the original
-		size
-
-		duplicate: -1 enable check state
-					0 all is ok (or we are not allocating canvas memory)
-					1 found a duplicate
-	*/
-
-	//int random_extra = 0;
-	//int random_offset = 1;
-/*
-	while (canvas_check_duplicate != 0) {
-
-		if (canvas_check_duplicate == -1) {
-			//fprintf(stderr,"alloc %d %d\n", canvas_check_duplicate, (int)c->c_size);
-			x = (t_pd *)t_getbytes(c->c_size);
-		} else if (canvas_check_duplicate == 1) {
-			//random_extra = rand () + random_offset;
-			//fprintf(stderr,"alloc %d %d %d\n", canvas_check_duplicate, (int)c->c_size, (int)c->c_size + random_extra);
-			//x = (t_pd *)t_getbytes(c->c_size + random_extra);
-			//fprintf(stderr,"duplicate\n");
-			y = x;
-			y = (t_pd *)t_resizebytes(x, c->c_size, 1);
-			x = (t_pd *)t_getbytes(c->c_size);
-			t_freebytes(y, sizeof(1));
-		}
-
-		canvas_check_duplicate = 0;
-		if (rm_start) {
-			t_redundant_mem *tmp = rm_start;
-			while (tmp->rm_next) {
-				//fprintf(stderr,"compare %lx %lx\n", (t_int)tmp->rm_canvas, (t_int)x);
-				if ((t_int)tmp->rm_canvas == (t_int)x) {
-					canvas_check_duplicate = 1;
-					break;
-				}
-				tmp = tmp->rm_next;
-			}
-			if (tmp && (t_int)tmp->rm_canvas == (t_int)x)
-				canvas_check_duplicate = 1;
-		}
-
-		//fprintf(stderr,"done alloc %d\n", canvas_check_duplicate);
-		//if (canvas_check_duplicate == 1) {
-		//	//fprintf(stderr,"duplicate\n");
-		//	if (!random_extra)
-		//		t_freebytes(x, sizeof(c->c_size));
-		//	else
-		//		t_freebytes(x, sizeof(c->c_size+random_extra));
-		//}
-		//
-		//if (!canvas_check_duplicate && random_extra) {
-		//	x = (t_pd *)t_resizebytes(x, c->c_size+random_extra, c->c_size);
-		//	break;
-		//}
-	}
-
-    if (!x) x = (t_pd *)t_getbytes(c->c_size);*/
 	x = (t_pd *)t_getbytes(c->c_size);
     *x = c;
     if (c->c_patchable)
@@ -118,7 +49,6 @@
             binbuf_free(((t_object *)x)->ob_binbuf);
     }
     if (c->c_size) t_freebytes(x, c->c_size);
-	x = NULL;
 }
 
 void gobj_save(t_gobj *x, t_binbuf *b)
@@ -138,6 +68,7 @@
 {
     t_pd *e_who;
     struct _bindelem *e_next;
+	int e_delayed_free;
 } t_bindelem;
 
 typedef struct _bindlist
@@ -147,12 +78,13 @@
 } t_bindlist;
 
 static int change_bindlist_via_graph = 0;
+static t_bindlist *change_bindlist = NULL;
 
 static void bindlist_cleanup(t_bindlist *x)
 {
 	//fprintf(stderr,"bindlist_cleanup\n");
 	t_bindelem *e, *e2;
-    if (x->b_list->e_who == NULL)
+    if (x->b_list->e_delayed_free == 1)
     {
 		e = x->b_list;
         x->b_list = e->e_next;
@@ -160,7 +92,7 @@
 		//fprintf(stderr,"success B1a\n");
     }
     for (e = x->b_list; e2 = e->e_next; e = e2)
-        if (e2->e_who == NULL)
+        if (e2->e_delayed_free == 1)
     {
         e->e_next = e2->e_next;
         freebytes(e2, sizeof(t_bindelem));
@@ -177,64 +109,88 @@
 
 static void bindlist_bang(t_bindlist *x)
 {
-	change_bindlist_via_graph = 1;
     t_bindelem *e;
+        int save = change_bindlist_via_graph;
+	t_bindlist *save_bindlist = change_bindlist;
+	change_bindlist_via_graph = 1;
     for (e = x->b_list; e; e = e->e_next)
-        pd_bang(e->e_who);
-	bindlist_cleanup(x);
-	change_bindlist_via_graph = 0;
+        if (e->e_who != NULL) pd_bang(e->e_who);
+	if (change_bindlist_via_graph > 1)
+		bindlist_cleanup(x);
+	change_bindlist_via_graph = save;
+	change_bindlist = save_bindlist;
 }
 
 static void bindlist_float(t_bindlist *x, t_float f)
 {
-	change_bindlist_via_graph = 1;
     t_bindelem *e;
+        int save = change_bindlist_via_graph;
+	t_bindlist *save_bindlist = change_bindlist;
+	change_bindlist_via_graph = 1;
     for (e = x->b_list; e; e = e->e_next)
-        pd_float(e->e_who, f);
-	bindlist_cleanup(x);
-	change_bindlist_via_graph = 0;
+        if (e->e_who != NULL) pd_float(e->e_who, f);
+	if (change_bindlist_via_graph > 1)
+		bindlist_cleanup(x);
+	change_bindlist_via_graph = save;
+	change_bindlist = save_bindlist;
 }
 
 static void bindlist_symbol(t_bindlist *x, t_symbol *s)
 {
-	change_bindlist_via_graph = 1;
     t_bindelem *e;
+        int save = change_bindlist_via_graph;
+	t_bindlist *save_bindlist = change_bindlist;
+	change_bindlist_via_graph = 1;
     for (e = x->b_list; e; e = e->e_next)
-        pd_symbol(e->e_who, s);
-	bindlist_cleanup(x);
-	change_bindlist_via_graph = 0;
+        if (e->e_who != NULL) pd_symbol(e->e_who, s);
+	if (change_bindlist_via_graph > 1)
+		bindlist_cleanup(x);
+	change_bindlist_via_graph = save;
+	change_bindlist = save_bindlist;
 }
 
 static void bindlist_pointer(t_bindlist *x, t_gpointer *gp)
 {
-	change_bindlist_via_graph = 1;
     t_bindelem *e;
+        int save = change_bindlist_via_graph;
+	t_bindlist *save_bindlist = change_bindlist;
+	change_bindlist_via_graph = 1;
     for (e = x->b_list; e; e = e->e_next)
-        pd_pointer(e->e_who, gp);
-	bindlist_cleanup(x);
-	change_bindlist_via_graph = 0;
+        if (e->e_who != NULL) pd_pointer(e->e_who, gp);
+	if (change_bindlist_via_graph > 1)
+		bindlist_cleanup(x);
+	change_bindlist_via_graph = save;
+	change_bindlist = save_bindlist;
 }
 
 static void bindlist_list(t_bindlist *x, t_symbol *s,
     int argc, t_atom *argv)
 {
-	change_bindlist_via_graph = 1;
     t_bindelem *e;
+        int save = change_bindlist_via_graph;
+	t_bindlist *save_bindlist = change_bindlist;
+	change_bindlist_via_graph = 1;
     for (e = x->b_list; e; e = e->e_next)
-        pd_list(e->e_who, s, argc, argv);
-	bindlist_cleanup(x);
-	change_bindlist_via_graph = 0;
+        if (e->e_who != NULL) pd_list(e->e_who, s, argc, argv);
+	if (change_bindlist_via_graph > 1)
+		bindlist_cleanup(x);
+	change_bindlist_via_graph = save;
+	change_bindlist = save_bindlist;
 }
 
 static void bindlist_anything(t_bindlist *x, t_symbol *s,
     int argc, t_atom *argv)
 {
-	change_bindlist_via_graph = 1;
     t_bindelem *e;
+        int save = change_bindlist_via_graph;
+	t_bindlist *save_bindlist = change_bindlist;
+	change_bindlist_via_graph = 1;
     for (e = x->b_list; e; e = e->e_next)
-        pd_typedmess(e->e_who, s, argc, argv);
-	bindlist_cleanup(x);
-	change_bindlist_via_graph = 0;
+        if (e->e_who != NULL) pd_typedmess(e->e_who, s, argc, argv);
+	if (change_bindlist_via_graph > 1)
+		bindlist_cleanup(x);
+	change_bindlist_via_graph = save;
+	change_bindlist = save_bindlist;
 }
 
 void m_pd_setup(void)
@@ -261,6 +217,7 @@
             t_bindelem *e = (t_bindelem *)getbytes(sizeof(t_bindelem));
             e->e_next = b->b_list;
             e->e_who = x;
+			e->e_delayed_free = 0;
             b->b_list = e;
         }
         else
@@ -272,8 +229,10 @@
             b->b_list = e1;
             e1->e_who = x;
             e1->e_next = e2;
+			e1->e_delayed_free = 0;
             e2->e_who = s->s_thing;
             e2->e_next = 0;
+			e2->e_delayed_free = 0;
             s->s_thing = &b->b_pd;
         }
     }
@@ -307,11 +266,13 @@
 
         t_bindlist *b = (t_bindlist *)s->s_thing;
         t_bindelem *e, *e2;
+	int delayed = change_bindlist_via_graph && change_bindlist==b;
         if ((e = b->b_list)->e_who == x)
         {
-			if (change_bindlist_via_graph)
-				e->e_who = NULL;
-			else {
+			if (delayed) {
+				change_bindlist_via_graph++;
+				e->e_delayed_free = 1;
+			} else {
             	b->b_list = e->e_next;
             	freebytes(e, sizeof(t_bindelem));
 			}
@@ -320,9 +281,10 @@
         else for (e = b->b_list; e2 = e->e_next; e = e2)
             if (e2->e_who == x)
         {
-			if (change_bindlist_via_graph) 
-				e2->e_who = NULL;
-			else {
+			if (change_bindlist_via_graph) {
+				change_bindlist_via_graph++;
+				e2->e_delayed_free = 1;
+			} else {
 		        e->e_next = e2->e_next;
 		        freebytes(e2, sizeof(t_bindelem));
 			}
@@ -331,15 +293,18 @@
         }
 
 		int count_valid = 0;
+		t_bindelem *e1 = NULL;
         for (e = b->b_list; e; e = e->e_next)
         {
-			if (e->e_who != NULL)
+			if (e->e_who != NULL && !e->e_delayed_free) {
 				count_valid++;
+				e1 = e;
+			}
 
 		}
 		if (count_valid == 1) {
-            s->s_thing = b->b_list->e_who;
-			if (!change_bindlist_via_graph) {
+            s->s_thing = e1->e_who;
+			if (!delayed) {
             	freebytes(b->b_list, sizeof(t_bindelem));
             	pd_free(&b->b_pd);
 			}
@@ -363,16 +328,19 @@
         t_bindelem *e, *e2;
         int warned = 0;
         for (e = b->b_list; e; e = e->e_next)
-            if (*e->e_who == c)
-        {
-            if (x && !warned)
-            {
-                zz();
-                post("warning: %s: multiply defined", s->s_name);
-                warned = 1;
-            }
-            x = e->e_who;
-        }
+		{
+            //if (e->e_who != NULL && *e->e_who == c)
+            if (e->e_delayed_free != 1 && *e->e_who == c)
+		    {
+		        if (x && !warned)
+		        {
+		            zz();
+		            post("warning: %s: multiply defined", s->s_name);
+		            warned = 1;
+		        }
+		        x = e->e_who;
+		    }
+		}
     }
     return x;
 }


More information about the L2Ork-dev mailing list