[PD-dev] GUI object crash on close when in subpatcher

Rama Gottfried rama.gottfried at gmail.com
Wed Apr 8 05:55:36 CEST 2015


Dear list,
I found something that seems like a bug to me, but I’m still not sure, it could be something in my code. Could someone take a look and tell me if I’m doing something incorrectly? 

The GUI object pasted below will sometimes crash on close when in a sub-patcher, but not in a top level patcher.

What is confusing to me is that the order of objects in the .pd file seems to make a difference.

On my system this patch crashes on close with a Segmentation Fault: 11:

#N canvas 627 164 450 300 10;
#N canvas 546 160 450 300 foo 0;
#X obj 117 115 basicgui;
#X obj 126 56 inlet;
#X connect 1 0 0 0;
#X restore 131 90 pd foo;

But this version of the same exact patch with only the creation order of objects in the file changed, does *not* crash:

#N canvas 627 164 450 300 10;
#N canvas 546 160 450 300 foo 0;
#X obj 126 56 inlet;
#X obj 117 115 basicgui;
#X connect 0 0 1 0;
#X restore 131 90 pd foo;

The crash log seems to point to a problem with the number of inlets while the linetraverser is running… but I’m not sure how to correct my code to avoid this.

Many thanks for any advice!
Rama


MacOS 10.10.2
Pd 0.46.6

Crash log:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       EXC_I386_GPFLT

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   pd                            	0x0000000106e7f59c obj_ninlets + 76
1   pd                            	0x0000000106e29bb9 linetraverser_next + 569
2   pd                            	0x0000000106e2b232 canvas_deletelinesfor + 50
3   pd                            	0x0000000106e33fb5 text_delete + 37
4   pd                            	0x0000000106e504b7 gobj_delete + 87
5   pd                            	0x0000000106e2e485 glist_delete + 597
6   pd                            	0x0000000106e3168d graph_delete + 61
7   pd                            	0x0000000106e504b7 gobj_delete + 87
8   pd                            	0x0000000106e2e485 glist_delete + 597
9   pd                            	0x0000000106e2aefd canvas_free + 109
10  pd                            	0x0000000106e79d14 pd_free + 68
11  pd                            	0x0000000106e56869 canvas_menuclose + 265
12  pd                            	0x0000000106e7d07b pd_typedmess + 1515
13  pd                            	0x0000000106e4d6b1 guiconnect_anything + 65
14  pd                            	0x0000000106e7d23d pd_typedmess + 1965
15  pd                            	0x0000000106e839e7 binbuf_eval + 2215
16  pd                            	0x0000000106e8ef78 socketreceiver_read + 648
17  pd                            	0x0000000106e8e80d sys_domicrosleep + 557
18  pd                            	0x0000000106e8e5c8 sys_microsleep + 24
19  pd                            	0x0000000106e8ab89 m_pollingscheduler + 857
20  pd                            	0x0000000106e8a738 m_mainloop + 56
21  pd                            	0x0000000106e8b485 sys_main + 501
22  pd                            	0x0000000106e974e2 main + 34
23  libdyld.dylib                 	0x00007fff905975c9 start + 1



// basicgui.c object:

#include "m_pd.h"
#include "g_canvas.h"

typedef struct _basicgui
{
    t_object    ob;
    t_glist     *glist;
    char        io_tag[256];
    int         height, width, exists;
    
} t_basicgui;

static t_class *basicgui_class;
t_widgetbehavior basicgui_widget;


static void basicgui_getrect(t_gobj *z, t_glist *glist,int *xp1, int *yp1, int *xp2, int *yp2)
{
    t_basicgui *x = (t_basicgui *)z;
    
    *xp1 = text_xpix(&x->ob, glist);
    *yp1 = text_ypix(&x->ob, glist);
    *xp2 = *xp1 + x->width;
    *yp2 = *yp1 + x->height;
    x->glist = glist;
}

static void basicgui_displace(t_gobj *z, t_glist *glist, int dx, int dy)
{
    t_basicgui *x = (t_basicgui *)z;
    sys_vgui(".x%lx.c move %lxBOX %d %d\n", glist_getcanvas(glist), z, dx, dy );
    x->ob.te_xpix += dx;
    x->ob.te_ypix += dy;
    
    int x1, x2, y1, y2;
    basicgui_getrect(z, glist, &x1, &y1, &x2, &y2);
    
    t_object *ob = pd_checkobject(&x->ob.te_pd);
    if (ob){
        glist_drawiofor(glist, ob, 0, x->io_tag, x->ob.te_xpix, x->ob.te_ypix, x2, y2);
        canvas_fixlinesfor(glist, &x->ob);
    }

}

static void basicgui_select(t_gobj *z, t_glist *glist, int state)
{}

static void basicgui_activate(t_gobj *z, t_glist *glist, int state)
{}

static void basicgui_delete(t_gobj *z, t_glist *glist)
{
    printf("%s %p \n", __FUNCTION__, z);

    t_canvas *canvas = glist_getcanvas(glist);
    
    if(canvas->gl_editor)
    {
        printf("%s deleting %p \n", __FUNCTION__, z);
        sys_vgui(".x%lx.c delete %lxBOX \n", glist_getcanvas(glist), z );

        t_basicgui *x = (t_basicgui *)z;
        t_object *ob = pd_checkobject(&x->ob.te_pd);
        if(ob && glist_isvisible(glist))
        {
            glist_eraseiofor(glist, ob, x->io_tag);
            canvas_deletelinesfor(canvas, ob);
        }
    }

}

void basicgui_drawElements(t_basicgui *x, t_gobj *z, t_glist *glist, int firstime)
{
    int x1, x2, y1, y2;
    basicgui_getrect(z, glist, &x1, &y1, &x2, &y2);
    if(firstime)
    {
        sys_vgui(".x%lx.c create rectangle %d %d %d %d -outline \"blue\" -fill \"\" -tags %lxBOX \n", glist_getcanvas(glist), x1, y1, x2, y2, z);
    }
    else
    {
        if (glist_isvisible(glist))
            sys_vgui(".x%lx.c coords %lxBOX %d %d %d %d \n", glist_getcanvas(glist), z, x1, y1, x2, y2);
    }
    
    t_object *ob = pd_checkobject(&x->ob.te_pd);
    if (ob){
        glist_drawiofor(glist, ob, firstime, x->io_tag, x1, y1, x2, y2);
    }
    if (firstime) /* raise cords over everything else */
        sys_vgui(".x%lx.c raise cord\n", glist_getcanvas(glist));
    
    x->exists = 1;
}

void basicgui_vis(t_gobj *z, t_glist *glist, int state)
{
  //  printf("%p %s state %d glist %p canvas %p\n", (t_basicgui *)z, __func__, state, glist, glist_getcanvas(glist));
    t_basicgui *x = (t_basicgui *)z;

    if(state)
    {
        basicgui_drawElements(x, z, glist, state);
    }
    else
    {
        if(x->exists)
        {
            basicgui_delete(z, glist);
            x->exists = 0;
        }
    }
   
    
}

void basicgui_save(t_gobj *z, t_binbuf *b)
{
    t_basicgui *x = (t_basicgui *)z;
    binbuf_addv(b, "ssiis;", gensym("#X"),gensym("obj"), (t_int)x->ob.te_xpix, (t_int)x->ob.te_ypix, gensym("basicgui"));

}


void basicgui_bang(t_basicgui *x)
{
    int x1, x2, y1, y2;
    basicgui_getrect((t_gobj *)x, x->glist, &x1, &y1, &x2, &y2);
    post("%x %s x1 %d y1 %d x2 %d y2 %d", x, __func__, x1, y1, x2, y2);
    post("text pix x %d y %d", text_xpix(&x->ob, x->glist), text_ypix(&x->ob, x->glist));
}

void *basicgui_new(void)
{
    t_basicgui *x = (t_basicgui *)pd_new(basicgui_class);
    if(x)
    {
        x->glist = (t_glist *)canvas_getcurrent();
        x->height = 10;
        x->width = 30;
        sprintf(x->io_tag, "%lxIOTAG", (long)x);
    }
    return (void *)x;
}

void basicgui_setup(void) {

    basicgui_class = class_new(gensym("basicgui"),
			       (t_newmethod)basicgui_new,
			       0,
			       sizeof(t_basicgui),
			       CLASS_DEFAULT,
			       0);

    class_addbang(basicgui_class, basicgui_bang);
    
    basicgui_widget.w_getrectfn = basicgui_getrect;
    basicgui_widget.w_displacefn = basicgui_displace;
    basicgui_widget.w_deletefn = basicgui_delete;
    basicgui_widget.w_visfn = basicgui_vis;
    basicgui_widget.w_selectfn = NULL;
    basicgui_widget.w_activatefn = NULL;
    basicgui_widget.w_clickfn = NULL;

    
    class_setsavefn(basicgui_class, basicgui_save);
    class_setwidget(basicgui_class, &basicgui_widget);
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puredata.info/pipermail/pd-dev/attachments/20150407/868a14f5/attachment-0001.html>


More information about the Pd-dev mailing list