Re: Glib::Dispatcher (multiple emit/write lockup)



On Tuesday 28 June 2005 04:15, Mario Sergio Fujikawa Ferreira wrote:

[snip]

> 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.

The POSIX Single Unix Specification provides in relation to write() that:

"Write requests to a pipe or FIFO shall be handled in the same way as a 
regular file with the following exceptions:

  ...

  Write requests of {PIPE_BUF} bytes or less shall not be interleaved with
  data from other processes doing writes on the same pipe. Writes of greater
  than {PIPE_BUF} bytes may have data interleaved, on arbitrary boundaries,
  with writes by other processes, whether or not the O_NONBLOCK flag of the
  file status flags is set.

  ..."

PIPE_BUF is never less than 512 and is usually 2048 in size.  Admittedly the 
standard only requires writes by different processes to be atomic with a 
write of a size not greater than that, but it would be odd if the same 
behaviour were not exhibited by different threads within one process.  If you 
are using Windows, I thought that it was POSIX compliant?

Unfortunaly gnome.org is down at the moment so I cannot look up your mailing 
list references, but why is it that mutexes around the write call don't solve 
the issue (if in fact different threads within the same process do not 
benefit from the POSIX atomicity guarantees)?  That should avoid concurrent 
writes to the Dispatcher pipe in every case.

Chris



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