hi,
like on so many occasions already, my original hasty response to
``dynamic etern/subpatch instantiation'' post was not precise.
I must say, first of all, that in all cases reported below, it is hard
to find any real bugs. These are `misfeatures', which do not break any
promises -- and the safeguards could have been omitted for performance
sake, or code simplicity, or whatever other reason...
1. I was right pointing at corrupted bindlist as a source of the
original ``duplicated toplevel patch'' crash. The proof is here
(toppatch.pd can be any patch file, [del 1000] is inserted in order
to wait through any window raising delays):
#N canvas 213 96 518 300 12;
#X obj 25 41 loadbang;
#X msg 25 91 bang \; pd open toppatch.pd . \; pd open toppatch.pd .;
#X obj 25 176 del 1000;
#X msg 25 231 \; pd-toppatch.pd menuclose;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
static void bindlist_anything(t_bindlist *x, t_symbol *s,
int argc, t_atom *argv)
{
t_bindelem *e = x->b_list;
#if CRASHY /* the loop we have now */
for (e = x->b_list; e; e = e->e_next)
pd_typedmess(e->e_who, s, argc, argv);
#else /* safer loop */
while (e)
{
t_pd *who = e->e_who;
e = e->e_next;
pd_typedmess(who, s, argc, argv);
}
#endif
}
2. I was wrong adding an example of a similar crash. The main
theme in both cases was self-destruction, but my example was much
more nasty. A direct cause of crashing in this case was such:
#N canvas 296 127 450 300 12;
#X obj 44 40 loadbang;
#X obj 44 79 del 1000;
#X msg 44 117 \; pd-crash find r \; x please do not crash;
#N canvas 43 0 376 332 crash 1;
#X obj 110 138 outlet;
#X obj 110 68 r x;
#X connect 1 0 0 0;
#X restore 44 202 pd crash;
#X msg 44 239 \; pd-crash cut;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 3 0 4 0;
void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv)
{
t_outconnect *oc = x->o_connections;
char c;
if (&c < stacklimit)
outlet_stackerror(x);
#if CRASHY /* the loop we have now */
else for (oc = x->o_connections; oc; oc = oc->oc_next)
typedmess(oc->oc_to, s, argc, argv);
#else /* safer loop */
else while (oc)
{
t_pd *dest = oc->oc_to;
oc = oc->oc_next;
typedmess(dest, s, argc, argv);
}
#endif
}
3. Of course my original `test.pd' example would keep crashing, until
the two safeguards are not applied to bang message, i.e. we need to
embellish also bindlist_bang() and outlet_bang().
4. In order to be really on the safe side, there always need to be
a [del 1000] object inserted after any patch-modifying loadbang.
Btw. under Gnome this delay may need to be even longer (I think there
is a window raising bug in Gnome or Sawfish; in my Gnome system it
is so annoying, that I finally deleted `after-raise' command from
pdtk_canvas_new in pd.tk; no such trouble under fvwm2).
5. But even after adding all these safeguards, there would still
be crashes, if the fatal message was clicked, instead of being
loadbanged. For example, using safer version of outlet_bang(),
the following (if named `crash-message.pd') will not crash upon
loading, but will crash after clicking ``please do not crash''
message.
#N canvas 296 127 424 295 12;
#X obj 44 18 loadbang;
#X obj 44 65 del 1000;
#X msg 44 112 \; pd-crash-message.pd selectall \; x please do not crash;
#X obj 44 195 r x;
#X msg 44 243 \; pd-crash-message.pd cut;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 3 0 4 0;
The simplest safeguard would be just an insertion of
``if (!y) return;'' into message_click().
6. Yet another source of crashing is sending `cut' message to
any canvas which is not visible.
Crashtof