Problem with gdk_input_add()/remove()




While writing a network application program, I encountered this
problem. I have a socket for the network connection. This socket has
both "read-ready" and "write-ready" handlers attached to it with the
gdk_input_add() function. If the socket becomes ready for both read
and write at the same time, and an error occurs while the first
handler function is executing, the handler tries to clean up by
removing both handlers with the gdk_input_remove() function. However,
doing this generates a bus error somewhere in the gdk library. See the
test program below for details.

My question is: Is this a bug in gtk/gdk or is it not legal to remove
an IO handler function while another IO handler function is executing?

I'm using gtk+ 1.0.6, glib 1.0.6 and Redhat Linux 5.2 (x86).


/* -------------------------------------------- */

Compile options:

	gcc -g -Wall -o gtkbug gtkbug.c `gtk-config --cflags --libs`

/* -------------------------------------------- */

strace output:

sigaction(SIGBUS, {0x8048700, [], SA_NOMASK|0xa3c8}, {0x400c2fb0, [], SA_STACK|SA_RESTART|SA_INTERRUPT|SA_ONESHOT|0x7fff900}) = 0
socketpair(PF_UNIX, SOCK_STREAM, , 0, [4, 5]) = 0
write(5, "x", 1)                        = 1
ioctl(3, FIONREAD, [0])                 = 0
select(5, [3 4], [4], [], NULL)         = 2 (in [4], out [4])
fstat(1, {st_mode=S_ISVTX|0402, st_size=0, ...}) = 0
mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000b000
ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0
write(1, "writefunc\n", 10)             = 10
write(1, "cleanup\n", 8)                = 8
--- SIGBUS (Bus error) ---
write(2, "gtkbug: gtkbug.c:42: sighan: Ass"..., 51gtkbug: gtkbug.c:42: sighan: Assertion `0' failed.
) = 51
sigprocmask(SIG_UNBLOCK, [ABRT], NULL)  = 0
getpid()                                = 596
kill(596, SIGABRT)                      = 0
--- SIGABRT (Aborted) ---
+++ killed by SIGABRT +++


/* -------------------------------------------- */

gdb backtrace:

(gdb) bt
#0  0x401ba811 in __kill ()
#1  0x401ba63f in raise (sig=6) at ../sysdeps/posix/raise.c:27
#2  0x401bb84f in abort () at ../sysdeps/generic/abort.c:83
#3  0x401b5416 in __assert_fail (assertion=0x804884a "0", 
    file=0x8048841 "gtkbug.c", line=42, function=0x804883a "sighan")
    at assert.c:54
#4  0x8048719 in sighan (sig=7) at gtkbug.c:42
#5  <signal handler called>
#6  0x400c1358 in gdk_event_wait ()
#7  0x400c0575 in gdk_event_get ()
#8  0x4005324d in gtk_main_iteration_do ()
#9  0x400531a7 in gtk_main_iteration ()
#10 0x40052ff9 in gtk_main ()
#11 0x80487be in main (argc=1, argv=0xbffff9c0) at gtkbug.c:64
(gdb) 


/* ----- gtkbug.c ------------------------------ */

#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <signal.h>
#include <assert.h>

int rtag;
int wtag;

void cleanup()
{
    printf("cleanup\n");

    gdk_input_remove(rtag);
    gdk_input_remove(wtag);
}

void readfunc(gpointer data, gint source, GdkInputCondition condition)
{
    int error = 1;

    printf("readfunc\n");

    if (error)
	cleanup();
}

void writefunc(gpointer data, gint source, GdkInputCondition condition)
{
    int error = 1;

    printf("writefunc\n");

    if (error)
	cleanup();
}

void sighan(int sig)
{
    assert(0);
}

int main(int argc, char** argv)
{
    int sv[2];
    int fd;

    gtk_init(&argc, &argv);

    signal(SIGBUS, sighan);

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0)
	exit(1);

    write(sv[1], "x", 1);

    fd = sv[0];

    rtag = gdk_input_add(fd, GDK_INPUT_READ, readfunc, NULL);
    wtag = gdk_input_add(fd, GDK_INPUT_WRITE, writefunc, NULL);

    gtk_main();

    return 0;
}

/* -------------------------------------------- */

-- 
Peter Österlund          Email:     peter.osterlund@mailbox.swipnet.se
Sköndalsvägen 35                    f90-pos@nada.kth.se
S-128 66 Sköndal         Home page: http://home1.swipnet.se/~w-15919
Sweden                   Phone:     +46 8 942647



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]