Re: Race condition during Dispatcher deconstruction



On Thu, 2008-01-03 at 09:10 -0600, Matt Hoosier wrote:
> Hi,
> 
> I've been observing a crash which shortly follows the deletion of a
> Glib::Dispatcher object. The scenario goes something like this:
> 
> * Dispatcher instance is allowed by mainloop thread
> * Some UI widget registers a callback on the dispatcher
> * Background thread does an emit()
> * UI thread deletes the widget, including reclaiming the dispatcher
> * When the mainloop becomes idle again, the GIOSource listening for
> the receiver side of the dispatcher wakes up and tries to deliver the
> signal to the now-reclaimed dispatcher
> 
> Specifically, I get a crash in the Dispatcher::pipe_io_handler
> function during a GIOSource [presumably, the one registered by the
> receiver side of the Dispatcher] callback execution.

I think this could/would happen, as in the case you mention the static
pipe read callback in the GUI thread will attempt to emit on the signal
object which the Glib::Dispatcher object has/had as a member; and if the
dispatcher object has been destroyed after the emitting thread emitted
on it but before the GUI thread invokes the callback, the signal object
will also have ceased to exist by the time the GUI thread emits on the
signal object.

You could use this:
http://efax-gtk.cvs.sourceforge.net/*checkout*/efax-gtk/efax-gtk/src/utils/notifier.h?revision=1.17
http://efax-gtk.cvs.sourceforge.net/*checkout*/efax-gtk/efax-gtk/src/utils/notifier.cpp?revision=1.11

To use it (unless you roll your own) you will also need:
http://efax-gtk.cvs.sourceforge.net/*checkout*/efax-gtk/efax-gtk/src/utils/io_watch.h?revision=1.6
http://efax-gtk.cvs.sourceforge.net/*checkout*/efax-gtk/efax-gtk/src/utils/io_watch.cpp

It is similar to a Glib::Dispatcher object but is safer - in particular
it detects the case you have mentioned (at the expense of slightly less
efficiency as it keeps a static std::set object for book keeping which
requires mutex locking and is invoked every time a new dispatcher object
is created or an old one destroyed).  It also detects a case where the
thread emitting on the dispatcher object is the same as the thread in
which the slot will execute.  In that case in theory a Glib::Dispatcher
object could lock-up if there are a large number of dispatchers in use
because if the pipe becomes full and blocks on write, it could never
read to unblock if the emitting (writing) and callback (reading) threads
are the same.

If you read the comments in the files I have mentioned then you will see
the point.

Chris




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