thread safety broken? (and Changes-1.2.txt)




Disclaimer: please don't take any of this as ragging on developers.I'm
            grateful for your efforts.

I'm working on a multithreaded application, an mpeg video player, that
I've been migrating to gtk for some time now.

About four or five months ago, I started out with gtk 1.0.  I'm not an
experienced X programmer, so when I started getting dreaded 'Xlib:
async reply error', I rapidly retreated to the most conservative
approach that various faqs, newsgroup postings, etc. described: I put
all gui activity into a single thread, and I had other threads use
that thread as an intermediary for any gui work.  This was reliable,
but added a lot of ugliness to my code.

A few weeks ago, I read something that indicated the 1.1 series was
incorporating better thread support.  Then I read Changes-1.2.txt.  I
thought "great! this will let me really clean up my code".  So I
proceeded to try and move to 1.1 with threads.

My experience so far has not been good.  I desperately wanted to make
this work.  I spent a lot of time pulling my hair out searching
mailing mailing list archives, FAQs, source, etc.  I've been stubborn
about reverting back to my 1.0 model because it's truly a pain in the
butt.  .

I often got deadlocks because the glib main loop lock and the gdk
global mutex were not acquired in the same order.  I've concluded for
now that thread safety in gtk+ simply isn't there yet.

I found out about XThreadsInit, which seems to work well in covering
the XAsyncReply problems.

For internal thread safety of gtk+/gdk/glib, I resort to using a mutex
to guard all access to gtk+/gdk/glib, and having only a single thread
invoke gtk_main.  

I do *not* call g_thread_init(), because doing so means that gtk+ will
deadlock even if I protect all my gui access with a mutex.  (This is
because interaction between gtk_main, which accesses the gdk and glib
mutex, and whatever gtk function my other threads might happen to
run).  By not calling g_thread_init(), the gdk mutex is not activated.
So far I'm OK, although I expect there are still nasty races between
the thread that invokes gtk_main and the rest.

I'm curious about whether I've made a mistake in drawing these
conclusions.  If not, I'd suggest amending Changes-1.2.txt with a
warning to prevent other newbies from wasting time in finding out the
same kind of stuff.

I also noticed the following errors in the Changes-1.2.txt:

>   - You must call g_thread_init(), then gtk_thread_init()
>     in a threaded GTK+ program.

gtk_thread_init doesn't exist anymore, right?  It looks like gdk_init
(invoked by gtk_init) automatically detects threads when g_thread_init 
has been called first.

>   - Idles, timeouts, and input functions are executed outside 
>     of the main GTK+ lock. So, if you need to call GTK+ 
>     inside of such a callback, you must surround the callback
>    with a gtk_thread_enter()/gtk_thread_leave() pair.

It's gdk_thread_enter() and gdk_thread_leave(), right?

>      b) Link with the libraries returned by:
> 
>           gtk-config --libs gthread
   

My gtk-config (from 1.1.11-1.1.13) doesn't understand anything about
gthread, although glib-config does.

Also, given the above observations, I tried to use testthreads.c and
found that it confirmed that gtk and threads are broken.  

-- Buck













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