GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Sun May 19, 2013 10:40 pm

All times are UTC




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: X Window System error
PostPosted: Tue Dec 13, 2011 3:57 am 
Offline
GTK+ Geek

Joined: Wed Mar 18, 2009 2:26 pm
Posts: 55
I have made a simple program with two threads.
One thread flashes a button and the other just does a printf ever 100msec.
After some time of flashing of the button I get the error as show below: the code is also show below:

The program 'thread_test' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadPixmap (invalid Pixmap parameter)'.
(Details: serial 1048 error_code 4 request_code 56 minor_code 0)
(Note to programmers: normally, X errors are reported asynchronously;
that is, you will receive the error a while after causing it.
To debug your program, run it with the --sync command line
option to change this behavior. You can then get a meaningful
backtrace from your debugger if you break on the gdk_x_error() function.)



Code:
// gcc -o thread_test -g button_flash.c `pkg-config --cflags --libs gtk+-2.0`

#include <gtk/gtk.h>

typedef struct
{
   GtkWidget * winx;
   GtkWidget * button;
   GdkColor Colors[2];
} xwindow;

xwindow * tw;

gint fast_thread()
{
   gint t;
   t = 0;
   for(;;)
   {
      g_usleep(100 * 1000);
      printf("FAST %d\n", t);
      t ++;
   }
   return 0;
}

gint slow_thread()
{
   gboolean phase;
   phase = FALSE;
   for(;;)
   {
      g_usleep(250 * 1000);
      gdk_threads_enter();
      if(phase == FALSE)
      {
         phase = TRUE;
         gtk_widget_modify_bg (tw->button, GTK_STATE_NORMAL, &tw->Colors[0]);
         gtk_widget_modify_bg (tw->button, GTK_STATE_PRELIGHT, &tw->Colors[0]);
      }
      else
      {
         phase = FALSE;
         gtk_widget_modify_bg (tw->button, GTK_STATE_NORMAL, &tw->Colors[1]);
         gtk_widget_modify_bg (tw->button, GTK_STATE_PRELIGHT, &tw->Colors[1]);
      }
      gdk_threads_leave();
   }
   return 0;
}

static gint i;
gint button_click(GtkWidget *button, gint data)
{
   for ( i = 0 ; i < 10 ; i ++)
   {
      gtk_button_set_label (GTK_BUTTON(tw->button), "set");
      g_usleep(1000 * 1000);
   }
   return 0;
}


gint main (gint argc, gchar *argv[])
{

   gtk_init (&argc, &argv);
   
   tw = g_slice_new (xwindow);
   
   // build window
   gdk_color_parse ("#000000", &tw->Colors[0]);// black
   gdk_color_parse ("#ffffff", &tw->Colors[1]);// white
   
   tw->winx = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   gtk_widget_set_size_request (tw->winx, 200, 100);
g_signal_connect (tw->winx, "destroy",G_CALLBACK (gtk_main_quit), NULL);

   tw->button = gtk_button_new();
   gtk_container_add (GTK_CONTAINER(tw->winx), tw->button);
   g_signal_connect (G_OBJECT (tw->button), "clicked", G_CALLBACK (button_click), NULL);
   gtk_widget_show_all(tw->winx);
   
   GError *err1, *err2;
   if(!g_thread_supported())
   {
     g_thread_init(NULL);
     gdk_threads_init();
   }
   else
   {
   }

   gtk_init (&argc, &argv);
   if(!g_thread_create((GThreadFunc)fast_thread, NULL, FALSE, &err1))
     {
      g_print("FAST Thread create failed: %s!!\n", err1->message );
      g_error_free ( err1 ) ;
     }
   else
   {
      g_print(" vvvvv  FAST vvvvv\n");
   }

   if(!g_thread_create((GThreadFunc)slow_thread, NULL, FALSE, &err2))
   {
      printf("SLOW Thread create failed: %s!!\n", err2->message );
      g_error_free ( err2 ) ;
   }
   else
   {
      g_print(" vvvvv  SLOW vvvvv\n");
   }
   gdk_threads_enter();
   gtk_main ();
   gdk_threads_leave();
   g_slice_free (xwindow, tw);

  return 0;
}


I have not been able to get any specific solutions for this.
Thanks in advance.

_________________
Hello, העלו, Здравствулте!


Top
 Profile  
 
 Post subject: Re: X Window System error
PostPosted: Wed Dec 14, 2011 9:52 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 507
Location: UK
Hi,

I have corrected your code and done a number of modifications to make it more correct. Your first problem was that threading was not correctly initialised. In your original code you were using GTK and GDK before initialising the internal threading locks, which is not allowed. I also set up a way for the threads to be exited cleanly so that slow_thread does not cause a crash on application exit. Threads can be useful, but do add to the complexity of your application.

I have also modified your button call-back so as to not use g_sleep(). The use of g_sleep() or any method to cause the main GUI thread to sleep is very bad and to the user it will look like the application has frozen. The way around this is to add another call-back using g_timeout_add_seconds(). This way your GUI is not locked (locking the GUI will also lock slow_thread()) and you get the expected result for the button.

Also note that I have made a number of minor changes to correct for the types of variables and function argument and return types. Also try to avoid the use of casting unless you have to, such as casting the return value from malloc(). This normally would hide potential errors in your code.

Note due to the simplicity of your code you could have coded everything without using threads, but using g_timeout_add(), so that you then just have timers running from your GUIs main loop. Just like what I did with the button press.

Please take your time to examine the code and ask questions if you need anything explained.

Code:
// gcc -o thread_test -g button_flash.c `pkg-config --cflags --libs gtk+-2.0  gthread-2.0`

#include <gtk/gtk.h>

typedef struct
{
   GtkWidget * winx;
   GtkWidget * button;
   GdkColor Colors[2];
} xwindow;

xwindow * tw;

volatile gint running = 1;
GThread *thread1, *thread2;

gpointer fast_thread(gpointer data)
{
   int t = 0;
   while (g_atomic_int_get(&running))
   {
      g_usleep(100 * 1000);
      printf("FAST %d\n", t);
      t ++;
   }
   return NULL;
}

gpointer slow_thread(gpointer data)
{
   gboolean phase = FALSE;
   while (g_atomic_int_get(&running))
   {
      g_usleep(1250 * 1000);
      gdk_threads_enter();
      if(phase == FALSE)
      {
         phase = TRUE;
         gtk_widget_modify_bg (tw->button, GTK_STATE_NORMAL, &tw->Colors[0]);
         gtk_widget_modify_bg (tw->button, GTK_STATE_PRELIGHT, &tw->Colors[0]);
      }
      else
      {
         phase = FALSE;
         gtk_widget_modify_bg (tw->button, GTK_STATE_NORMAL, &tw->Colors[1]);
         gtk_widget_modify_bg (tw->button, GTK_STATE_PRELIGHT, &tw->Colors[1]);
      }
      gdk_threads_leave();
   }
   return NULL;
}

static gint i;

gboolean button_timeout(gpointer data)
{
   if (i < 10) {
      gchar *s = g_strdup_printf("set %i", i);
      gtk_button_set_label(GTK_BUTTON(data), s);
      ++i;
      g_free(s);
      return TRUE;
   }
   return FALSE;
}

void button_click(GtkWidget *button, gpointer data)
{
   i = 0;
   button_timeout(button);

   g_timeout_add_seconds(1, button_timeout, button);
}

void destroy_cb(GtkObject *object, gpointer user_data)
{
   // Must kill the threads here before carrying on
   g_atomic_int_set(&running, 0);
   g_thread_join(thread1);

   // Note locking for slow_thread()
   gdk_threads_leave();
   g_thread_join(thread2);
   gdk_threads_enter();

   gtk_main_quit();
}

int main (int argc, char *argv[])
{
   GError *err1, *err2;

   if(!g_thread_supported())
   {
     g_thread_init(NULL);
     gdk_threads_init();
   }
   else
   {
      return 1;
   }
   gdk_threads_enter();
   gtk_init (&argc, &argv);
   
   tw = g_slice_new (xwindow);
   
   // build window
   gdk_color_parse ("#000000", &tw->Colors[0]);// black
   gdk_color_parse ("#ffffff", &tw->Colors[1]);// white
   
   tw->winx = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   gtk_widget_set_size_request (tw->winx, 200, 100);
   g_signal_connect (tw->winx, "destroy",G_CALLBACK (destroy_cb), NULL);

   tw->button = gtk_button_new();
   gtk_container_add (GTK_CONTAINER(tw->winx), tw->button);
   g_signal_connect (G_OBJECT (tw->button), "clicked", G_CALLBACK (button_click), NULL);
   gtk_widget_show_all(tw->winx);
   
   if(!(thread1 = g_thread_create(fast_thread, NULL, TRUE, &err1)))
   {
      g_print("FAST Thread create failed: %s!!\n", err1->message );
      g_error_free ( err1 ) ;
   }
   else
   {
      g_print(" vvvvv  FAST vvvvv\n");
   }

   if(!(thread2 = g_thread_create(slow_thread, NULL, TRUE, &err2)))
   {
      printf("SLOW Thread create failed: %s!!\n", err2->message );
      g_error_free ( err2 ) ;
   }
   else
   {
      g_print(" vvvvv  SLOW vvvvv\n");
   }

   gtk_main ();
   gdk_threads_leave();

   g_slice_free (xwindow, tw);

   return 0;
}

_________________
E.


Top
 Profile  
 
 Post subject: Re: X Window System error
PostPosted: Thu Dec 15, 2011 1:11 am 
Offline
GTK+ Geek

Joined: Wed Mar 18, 2009 2:26 pm
Posts: 55
Thanks Boss

_________________
Hello, העלו, Здравствулте!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group