GNOME Bugzilla – Bug 350076
Multithreaded GTK applications crash in most/all idle callbacks
Last modified: 2006-08-05 18:26:50 UTC
Steps to reproduce: #include <gtk/gtk.h> #include <unistd.h> #include <pthread.h> static GtkWidget *vbox; static bool program_quit=false; void *thread_function(void *) { sleep(3); while(!program_quit){ gdk_threads_enter (); printf("Create widget\n"); GtkWidget *entry=gtk_entry_new(); gtk_box_pack_start(GTK_BOX(vbox), entry, true, // expand true, // fill 0); // padding gtk_widget_show(entry); gdk_threads_leave (); usleep(5*1000); gdk_threads_enter (); gtk_entry_set_alignment (GTK_ENTRY(entry), 0.75); printf("Destroy widget\n"); gtk_widget_destroy(entry); gdk_threads_leave (); } return NULL; } static gboolean delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { gtk_main_quit (); return FALSE; } int main( int argc, char *argv[] ) { pthread_t tid; gtk_init (&argc, &argv); GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); vbox = gtk_vbox_new(FALSE,0); gtk_container_add (GTK_CONTAINER (window), vbox); gtk_widget_show_all (window); pthread_create(&tid,NULL,thread_function,NULL); gtk_main (); program_quit=true; sleep(3); return 0; } Stack trace: Run the test case for some seconds (up to one minute) and it will crash. The crash will occur inside the function recompute_idle_func of GtkEntry.c This function is called from the Gtkmain thread, but if during waiting inside GDK_THREADS_ENTER another thread deletes the GtkEntry (of course being locked by GDK_THREADS_ENTER/GDK_THREADS_LEAVE), this function will still continue after GDK_THREADS_ENTER and crash. In my oppinion this is a general problem for all idle functions used in all GtkObjects. The Glib should provide a function to check if the callback is still valid somehing like the following. This function should be called directly after GDK_THREADS_ENTER in each idle_callback and return if not valid (of course after calling GDK_THREADS_LEAVE). BOOL is_callback_valid(gpointer data) { GMainContext *context=g_main_context_default(); GSource *src=g_main_context_find_source_by_user_data (GMainContext *context, gpointer user_data); return (src!=NULL); } ############################################################################## Code from GtkEntry.c: static gboolean recompute_idle_func (gpointer data) { GtkEntry *entry; GDK_THREADS_ENTER (); entry = GTK_ENTRY (data); entry->recompute_idle = 0; if (gtk_widget_has_screen (GTK_WIDGET (entry))) { gtk_entry_adjust_scroll (entry); gtk_entry_queue_draw (entry); update_im_cursor_location (entry); } GDK_THREADS_LEAVE (); return FALSE; } Other information: No.
See bug 321886 for the required changes to make this work more reliably. *** This bug has been marked as a duplicate of 321886 ***