After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 534573 - Race condition with multiple threads and gdk_pixmap_get_type
Race condition with multiple threads and gdk_pixmap_get_type
Status: RESOLVED NOTABUG
Product: gtk+
Classification: Platform
Component: Backend: X11
unspecified
Other All
: Normal critical
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2008-05-24 00:56 UTC by Stanley
Modified: 2008-06-17 04:04 UTC
See Also:
GNOME target: ---
GNOME version: 2.9/2.10



Description Stanley 2008-05-24 00:56:01 UTC
Steps to reproduce:
  The problem occurs with embedded application;  i am looking for some 
verification and/or workaround of the problem.  The application is built
on top GNU Classpath with DirectFB as backend (don't think it's relevant,
but provided for completeness). Providing full backtrace for 2 threads
(<= are static functions). Crash can be reproduced occasionally.

Stack trace:
1 /opt/apogee/lib/libgdk-directfb-2.0.so.0(gdk_pixmap_get_type+0x3c)[0x40b48754]
1 /opt/apogee/lib/libgdk-directfb-2.0.so.0(gdk_pixmap_new+0x4f0)[0x40b776e0]
1 /opt/apogee/lib/libgtk-directfb-2.0.so.0[0x407919cc] <= gtk_gc_new
1 /opt/apogee/lib/libglib-2.0.so.0(g_cache_insert+0xd8)[0x40ee1e0c]
1 /opt/apogee/lib/libgtk-directfb-2.0.so.0(gtk_gc_get+0x8c)[0x40791644]
1 /opt/apogee/lib/libgtk-directfb-2.0.so.0[0x408d4d18] <= ??
1 /opt/apogee/lib/libgobject-2.0.so.0(g_cclosure_marshal_VOID__VOID+0xf4)[0x40e95874]
1 /opt/apogee/lib/libgobject-2.0.so.0[0x40e747b0] <= g_type_class_meta_marshal
1 /opt/apogee/lib/libgobject-2.0.so.0(g_closure_invoke+0x1f0)[0x40e74364]
1 /opt/apogee/lib/libgobject-2.0.so.0[0x40e946a0] <= signal_emit_unlocked_R
1 /opt/apogee/lib/libgobject-2.0.so.0(g_signal_emit_valist+0x9a0)[0x40e93ac8]
1 /opt/apogee/lib/libgobject-2.0.so.0(g_signal_emit+0x38)[0x40e93e98]
1 /opt/apogee/lib/libgtk-directfb-2.0.so.0[0x408d1360] <= gtk_style_realize
1 /opt/apogee/lib/libgtk-directfb-2.0.so.0(gtk_style_attach+0x1ec)[0x408d0fe8]
1 /opt/apogee/lib/libgtk-directfb-2.0.so.0[0x40a09b8c] <= gtk_window_realize
1 /opt/apogee/lib/libgobject-2.0.so.0(g_cclosure_marshal_VOID__VOID+0xf4)[0x40e95874]
1 /opt/apogee/lib/libgobject-2.0.so.0[0x40e747b0] <= g_type_class_meta_marshal
1 /opt/apogee/lib/libgobject-2.0.so.0(g_closure_invoke+0x1f0)[0x40e74364]
1 /opt/apogee/lib/libgobject-2.0.so.0[0x40e946a0] <= signal_emit_unlocked_R
1 /opt/apogee/lib/libgobject-2.0.so.0(g_signal_emit_valist+0x9a0)[0x40e93ac8]
1 /opt/apogee/lib/libgobject-2.0.so.0(g_signal_emit+0x38)[0x40e93e98]
1 /opt/apogee/lib/libgtk-directfb-2.0.so.0(gtk_widget_realize+0x280)[0x409ee61c]
1 /opt/apogee/lib/classpath/libgtkpeer.so(Java_gnu_java_awt_peer_gtk_GtkWindowPeer_realize+0x64)[0x406014c8]

2 /opt/apogee/lib/libgdk-directfb-2.0.so.0(gdk_pixmap_get_type+0x3c)[0x40b48754]
2 /opt/apogee/lib/libgtk-directfb-2.0.so.0[0x409f1e5c] <= event_window_is_still_viewable
2 /opt/apogee/lib/libgtk-directfb-2.0.so.0[0x409f1fac] <= gtk_widget_event_internal
2 /opt/apogee/lib/libgtk-directfb-2.0.so.0(gtk_widget_event+0x180)[0x409f1c18]
2 /opt/apogee/lib/libgtk-directfb-2.0.so.0(gtk_main_do_event+0x468)[0x40802ec8]
2 /opt/apogee/lib/libgdk-directfb-2.0.so.0[0x40b6d524] <= gdk_event_send_client_message_by_window
2 /opt/apogee/lib/libgdk-directfb-2.0.so.0[0x40b6d684] <= ??
2 /opt/apogee/lib/libglib-2.0.so.0[0x40f4bf24] <= g_io_unix_dispatch
2 /opt/apogee/lib/libglib-2.0.so.0[0x40f06f50] <= g_main_dispatch
2 /opt/apogee/lib/libglib-2.0.so.0(g_main_context_dispatch+0x94)[0x40f0888c]
2 /opt/apogee/lib/libglib-2.0.so.0[0x40f08df4] <= g_main_context_iterate
2 /opt/apogee/lib/libglib-2.0.so.0(g_main_loop_run+0x420)[0x40f09764]
2 /opt/apogee/lib/libgtk-directfb-2.0.so.0(gtk_main+0x130)[0x40802180]
2 /opt/apogee/lib/classpath/libgtkpeer.so(Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMain+0x20)[0x405fe058]



Other information:
In my case, both threads ((2) running gtk_main()) and ((1) drawing 
a window) eventually call gdk_pixmap_get_type() function.  This function uses
static variable to protect from double initialization of GdkPixmap type, which
(depending on the timing) is useless in presence of multiple threads.  I have
not seen any bugs related to this, but if somebody can provide some 
guidance/advice on how to handle this, that would be appreciated 
(unfortunately, i can not upgrade to latest GTK due to customer issues).  
Thanks.
Comment 1 Tim Janik 2008-06-16 15:02:28 UTC
You cannot use Gtk+ & Gdk simultaneously in two threads, you need to use GDK_THREADS_ENTER(); GDK_THREADS_LEAVE(); around your uses.
Comment 2 Andrew Cowie 2008-06-17 02:46:34 UTC
I remember looking at the code in Classpath's AWT "GTK peer". You're going to have a hard time messing with it. Their source code in that area even says:

classpath/gnu/java/awt/peer/gtk/GtkImage.java:116
"
  /**
   * Lock that should be held for all gdkpixbuf operations. We don't use
   * the global gdk_threads_enter/leave functions in most places since
   * most gdkpixbuf operations can be done in parallel to drawing and 
   * manipulating gtk widgets.
   */
"

It is not correct for the reason of the very problem you hit. You see this elsewhere in GTK too: module loading and type registration is not race safe. [Which is documented and so be it. A shame, though, as there doesn't seem to be much else standing in the way of GdkPixbuf being usable concurrently. Alas]

They *do* use gdk_threads_enter/leave() manually in most of their C code, so I'd assess that this is a bug in glibj, but that's up to them.

Pity about being stuck with an old version GTK; if you weren't then you could use java-gnome where all the GDK locking is done properly and you can use GTK properly and not have to mess around with all that AWT/Swing crap.

AfC
Comment 3 Matthias Clasen 2008-06-17 03:01:17 UTC
> A shame, though, as there doesn't seem to be
> much else standing in the way of GdkPixbuf being usable concurrently.

Once you cleared that hurdle (gtype), you run into non threadsafe image libraries (like librsvg using pango).
Comment 4 Andrew Cowie 2008-06-17 03:55:47 UTC
Sure. I only mention it because right now GdkPixbufFormat includes the ability to nominate a format [loader?] as safe with GDK_PIXBUF_FORMAT_THREADSAFE [and most of the formats are so marked], but it doesn't seem that we are able to offer a way for people to make use of that.

Image loading is one of those intensive things that might benefit from being able to happen concurrently, as was done with GtkFileChooser. The difference of course is that GtkFileChooser is under our control; people hammering away on gdk_pixbuf_new() is not.

AfC
Comment 5 Matthias Clasen 2008-06-17 04:04:48 UTC
Yeah.

Unfortunately, the threadsafe-loader thing is somewhat problematic together with
incremental loading.

Imagine an using a pixbuf loader to load an svg in the background, gdk-pixbuf takes the lock, in the meantime, gtk loads an svg icon for a button. oops