[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