Glib::Dispatcher (multiple emit/write lockup)



Hi,

I have an application running multiple threads and making heavy use of dispatchers. The application seemed to lock up erractically.

$ kill -11 app_id
$ gdb app core

Doing some gdb back tracing, it all traced back to dispatch emit() then
to the write(2) system call.

I added a few fprintf(stderr, "") traces to glibmm dispatch.cc code so that I could pin point exactly where the problem occured. It seems to me that it is a problem with reentrancy since nothing guarantees that the write(2) call on the sender is atomic.

	Which is reinforced by the comment right below the write(2)
call on the DispatchNotifier::send_notification() method on

http://cvs.gnome.org/viewcvs/glibmm/glib/glibmm/dispatcher.cc?rev=1.12&view=markup

// All data must be written in a single call to write(), otherwise we can't // guarantee reentrancy since another thread might be scheduled between two
// write() calls.  The manpage is a bit unclear about this -- but I hope
// it's safe to assume immediate success for the tiny amount of data we're
// writing.

Well, I am hitting a wall here. Glib::Dispatcher is not reentrant and there is little I can do about it. Adding per Dispatcher mutex protections around the write(2) system call do-while loop

  while (sender_mutex_.trylock() == false)
    Glib::Thread::yield();

  do
    n_written = write(fd_sender_, &data, sizeof(data));
  while(n_written < 0 && errno == EINTR);

  sender_mutex_.unlock();

does not protect against lockups. Nor does adding a mutex inside Dispatcher::emit().

void Dispatcher::emit()
{
  Glib::Mutex::Lock lock_(mutex);
  notifier_->send_notification(this);
}

	Checking the mailing lists, I found some interesting remarks

http://mail.gnome.org/archives/gtkmm-list/2002-September/msg00000.html

which do point out the reentrancy problem.

	There is a suggested solution at

http://mail.gnome.org/archives/gtkmm-list/2002-September/msg00008.html

pointing out that a lock-free FIFO multiple-writers-single-reader could be the solution. I do agree that this is non trivial.

Has anyone worked on such a solution? I did a very ugly work around in the mean time.

void Dispatcher::emit()
{
  Glib::usleep(1000);
  notifier_->send_notification(this);
}

	I'll probably add a rand addition to that to avoid timed
collisions. However, this is an undesirable at best. :)

	Any takers?




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