pthread problem w/ GtkGLext



I'm porting a pthreaded OpenGL application to GTK+ and have run into problems getting the threading to work.

I've written a simplified example of what I'm trying to do threadwise and it's core dumping on me. The program is supposed to let you open multiple windows in separate threads where a timer updates a label. It opens the first window but then core dumps.

Any and all help appreciated! :)

--
------------------------------------------------------------------------
Ray Clouse
STICS Lab
ray.clouse AT boeing.com			Don't fear the penguins.
clouse AT rayclouse.org
#include /usr/include/make/commondefs

CFLAGS  = -g `pkg-config gtk+-2.0 --cflags --libs --libs gthread-2.0` \
	-D_REENTRANT -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64

LDFLAGS	= -lpthread -lm
includedir = /usr/include/gtk-2.0/gtk/
LDADD   = `pkg-config gtk+-2.0 --libs`


default: main

main: Makefile main.c 
	$(CC) $(CFLAGS) $(LDFLAGS) main.c \
        -o main
clean: 
	rm *.o
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib.h>
#include <glib/gthread.h>
#include <semaphore.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>

#ifndef HAVE_DEFINES
# define HAVE_DEFINES
# define MAX_WINDOWS 10
# define MAX_THREADS 10
#endif

typedef struct 
{
  int counter;
  GtkWidget	*label;
} timeoutargs;

typedef struct
{
  int             threadnum;
  GtkWidget  	 *viewwindow;
  pthread_t       pthread;
  pthread_mutex_t taskmutex;
  pthread_cond_t  taskcond;
} viewthreadargs;

void
on_quit_activate                      (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  gtk_main_quit();
}

void
on_viewwindow_delete_event             (GtkWidget     *window,
                                        gpointer         user_data)
{
  gtk_widget_destroy(window);
}

void
on_exit2_activate                      (GtkWidget     *button,
                                        gpointer       user_data)
{
  GtkWidget *window = (GtkWidget *) user_data;
  
  gtk_widget_destroy(window);
}

gint counter_callback(gpointer *data) 
{
printf("begin counter_callback\n");
  timeoutargs *t1 = (timeoutargs *) data;
printf("1\n");
  char *s1;
  
  t1->counter++;
printf("2\n");
  sprintf(s1, "%d", t1->counter);
printf("3\n");
  gdk_threads_enter(); 
printf("4\n");
  gtk_label_set_text(GTK_LABEL(t1->label), s1);
printf("5\n");
  gdk_threads_leave(); 
printf("end counter_callback\n");
}

GtkWidget*
create_viewwindow (void)
{
  GtkWidget *viewwindow;
  GtkWidget *vbox4;
  GtkWidget *menubar3;
  GtkWidget *menuitem9;
  GtkWidget *menuitem9_menu;
  GtkWidget *separatormenuitem3;
  GtkWidget *exit2;
  GtkAccelGroup *accel_group;
  timeoutargs *targ;

printf("begin create_viewwindow\n");
  accel_group = gtk_accel_group_new ();

  viewwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (viewwindow), ("Thread Test View"));

  vbox4 = gtk_vbox_new (FALSE, 0);
  gtk_widget_show (vbox4);
  gtk_container_add (GTK_CONTAINER (viewwindow), vbox4);

  menubar3 = gtk_menu_bar_new ();
  gtk_widget_show (menubar3);
  gtk_box_pack_start (GTK_BOX (vbox4), menubar3, FALSE, FALSE, 0);

  menuitem9 = gtk_menu_item_new_with_mnemonic ("_File");
  gtk_widget_show (menuitem9);
  gtk_container_add (GTK_CONTAINER (menubar3), menuitem9);

  menuitem9_menu = gtk_menu_new ();
  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem9), menuitem9_menu);

  separatormenuitem3 = gtk_menu_item_new ();
  gtk_widget_show (separatormenuitem3);
  gtk_container_add (GTK_CONTAINER (menuitem9_menu), separatormenuitem3);
  gtk_widget_set_sensitive (separatormenuitem3, FALSE);

  exit2 = gtk_menu_item_new_with_mnemonic ("E_xit");
  gtk_widget_show (exit2);
  gtk_container_add (GTK_CONTAINER (menuitem9_menu), exit2);

  g_signal_connect ((gpointer) viewwindow, "delete_event",
                    G_CALLBACK (on_viewwindow_delete_event),
                    NULL);
  g_signal_connect ((gpointer) exit2, "activate",
                    G_CALLBACK (on_exit2_activate),
                    viewwindow);

  if ((targ = (timeoutargs *) calloc(1, sizeof(timeoutargs))) == NULL) {
    printf("Cannot calloc timeout arg data.\n");
    return NULL;
  }
  targ->label = gtk_label_new ("0");
  targ->counter = 0;

  gtk_box_pack_start (GTK_BOX (vbox4), targ->label, TRUE, TRUE, 0);
  gtk_widget_show(targ->label);
  g_timeout_add((guint32) 1000, 
  	(GtkFunction) counter_callback, 
	(gpointer) targ);

  gtk_window_add_accel_group (GTK_WINDOW (viewwindow), accel_group);

printf("end create_viewwindow\n");
  return viewwindow;
}

int
create_view_wrapper(viewthreadargs *vtargs)
{
printf("begin create_view_wrapper\n");
 gdk_threads_enter(); 
  vtargs->viewwindow = create_viewwindow();
  gtk_container_set_reallocate_redraws(GTK_CONTAINER(vtargs->viewwindow), 
  	TRUE);
  gtk_widget_show(vtargs->viewwindow);
  gdk_flush();
  gdk_threads_leave(); 
printf("end create_view_wrapper\n");
}

int
on_create_view_activate               (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  pthread_t t1;
  struct sched_param param1;
  viewthreadargs *vtargs;
  GError *error = NULL;

printf("begin on_create_view_activate\n");
  if ((vtargs = (viewthreadargs *) calloc(1, sizeof(viewthreadargs))) 
  	== NULL) {
    printf(" on_create_view_activate: Cannot calloc view window thread info.\n");
    return -1;
  }
 
  if ((pthread_create(&t1, 
  	NULL, 
	(void *) create_view_wrapper, 
	vtargs)) != 0) {
    printf(" Problem pthread_create\n");
    return -1;
  }

printf("end on_create_view_activate\n");
  return 1;
}

GtkWidget*
create_mainwindow (void)
{
  GtkWidget *mainwindow;
  GtkWidget *vbox1;
  GtkWidget *menubar1;
  GtkWidget *menuitem1;
  GtkWidget *menuitem1_menu;
  GtkWidget *separatormenuitem1;
  GtkWidget *quit1;
  GtkWidget *create_view1;
  GtkWidget *label1;
  GtkAccelGroup *accel_group;

  accel_group = gtk_accel_group_new ();

  mainwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (mainwindow), "Thread Test");

  vbox1 = gtk_vbox_new (FALSE, 0);
  gtk_widget_show (vbox1);
  gtk_container_add (GTK_CONTAINER (mainwindow), vbox1);

  menubar1 = gtk_menu_bar_new ();
  gtk_widget_show (menubar1);
  gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0);

  menuitem1 = gtk_menu_item_new_with_mnemonic ("_File");
  gtk_widget_show (menuitem1);
  gtk_container_add (GTK_CONTAINER (menubar1), menuitem1);

  menuitem1_menu = gtk_menu_new ();
  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem1), menuitem1_menu);

  separatormenuitem1 = gtk_menu_item_new ();
  gtk_widget_show (separatormenuitem1);
  gtk_container_add (GTK_CONTAINER (menuitem1_menu), separatormenuitem1);
  gtk_widget_set_sensitive (separatormenuitem1, FALSE);

  create_view1 = gtk_menu_item_new_with_mnemonic ("Create _View");
  gtk_widget_show (create_view1);
  gtk_container_add (GTK_CONTAINER (menuitem1_menu), create_view1);

  quit1 = gtk_image_menu_item_new_from_stock ("gtk-quit", accel_group);
  gtk_widget_show (quit1);
  gtk_container_add (GTK_CONTAINER (menuitem1_menu), quit1);

  g_signal_connect ((gpointer) quit1, "activate",
                    G_CALLBACK (on_quit_activate),
                    NULL);
  g_signal_connect ((gpointer) create_view1, "activate",
                    G_CALLBACK (on_create_view_activate),
                    NULL);

  gtk_window_add_accel_group (GTK_WINDOW (mainwindow), accel_group);
  
  label1 = gtk_label_new("Main wind0w");
  gtk_box_pack_start (GTK_BOX (vbox1), label1, FALSE, FALSE, 0);
  gtk_widget_show (label1);
 
  return mainwindow;
}

int
main (int argc, char *argv[])
{
  GtkWidget *mainwindow;
  sigset_t        sig_to_block;
  int i, j;

   /* init glib threads stuff for gtk */
  g_thread_init(NULL);
  gdk_threads_init();

 /* Setup the signals to block, threads will inherit this mask... */
  sigemptyset(&sig_to_block);
  /* Block SIGPIPE so the write to sockets will not get us when socket closed */
  sigaddset(&sig_to_block, SIGPIPE);
  /* Block SIG INT,TERM,SEGV so we can catch to close down and exit... */
  sigaddset(&sig_to_block, SIGINT);
  sigaddset(&sig_to_block, SIGTERM);
  sigaddset(&sig_to_block, SIGSEGV);
  pthread_sigmask(SIG_BLOCK, &sig_to_block, NULL); 

  gtk_set_locale ();
  gtk_init (&argc, &argv);

  mainwindow = create_mainwindow ();
  gtk_widget_show (mainwindow);

  gdk_threads_enter();
  gtk_main ();
  gdk_threads_leave();
  return 0;
}


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