GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Thu Aug 28, 2014 3:07 pm

All times are UTC




Post new topic Reply to topic  [ 7 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: 62
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: 745
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: 62
Thanks Boss

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


Top
 Profile  
 
 Post subject: Re: X Window System error
PostPosted: Fri Oct 18, 2013 6:24 am 
Offline
GTK+ Geek

Joined: Wed Mar 18, 2009 2:26 pm
Posts: 62
Hello errol

I have seen the code and found that the modified code works well on ubuntu 11.10 but does not work on ubuntu 12.04.
here is the reason...
Code:
   if(!g_thread_supported())
   {
     g_thread_init(NULL);
     gdk_threads_init();
   }
   else
   {
      return 1;
   }


on ubuntu 12.04 it keeps exiting at this part, if I remove the "return 1" and test, it works but with the same crash and error?

What is the difference between the two 11.10 and 12.04.

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


Top
 Profile  
 
 Post subject: Re: X Window System error
PostPosted: Fri Oct 18, 2013 7:22 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 745
Location: UK
Hello,

With regards to your threading question, I do not know the difference between the two Ubuntu versions. If you can state how you are compiling your code and to which versions of GTK and Glib you are compiling against that would help. Your original code was designed for GTK+ v2 but Ubuntu v12.04 uses GTK+ v3.4.

That section of code is to test if the threading is enabled. If it is not enabled the it just exits else it initialises the GDK locking etc.

_________________
E.


Top
 Profile  
 
 Post subject: Re: X Window System error
PostPosted: Fri Oct 18, 2013 8:46 am 
Offline
GTK+ Geek

Joined: Wed Mar 18, 2009 2:26 pm
Posts: 62
Hello errol

On my Ubuntu 11.10 system I am using the following version of GTK:
||/ Name Version Description
+++-============================-============================-========================================================================
ii libgtk-3-0 3.2.0-0ubuntu6 GTK+ graphical user interface library
ii libgtk2.0-0 2.24.6-0ubuntu5 The GTK+ graphical user interface library

Where as on Ubuntu 12.04 the version of GTK is:
||/ Name Version Description
+++-============================-============================-========================================================================
ii libgtk-3-0 3.4.2-0ubuntu0.5 GTK+ graphical user interface library
ii libgtk2.0-0 2.24.10-0ubuntu6 GTK+ graphical user interface library

Heres what i noticed, on my 11.10 system the improved code that you gave me works, and I do understand that g_thread_supported() checks if the thread system is enabled, but if it is not enabled the condition statement enables it with g_thread_init(). All this seems logical.
But on 12.04 the g_thread_supported() returns TRUE so it skips the initialization. Then if I just forcefully skip the check and unconditionally place the two lines of code ...

Code:
     g_thread_init(NULL);
     gdk_threads_init();

the code example works and no more errors. I applied the same in the larger version of the program and it worked over there too.
Do you know why this happens, I mean if the thread system is enabled as reported by g_thread_supported() then there would be no need to do "g_thread_init(NULL)" and "gdk_threads_init()"?

Thanks again for the quick reply.

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


Top
 Profile  
 
 Post subject: Re: X Window System error
PostPosted: Wed Oct 23, 2013 2:39 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 745
Location: UK
Threading has changed a bit in Glib v2.32 and I had an error in the code I gave you some time ago that worked then. Now with the change in Glib threads in v2.32 my error shows up.

Note that from GTK+ v3.6 gdk_thread_enter() and gdk_thread_leave() are now deprecated, so should now not be used. All GUI interactions should be done in the main thread.

_________________
E.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 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