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

2005-06-30 Thread Chris Vine
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.12view
=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/msg0.html

 which do point out the reentrancy problem.

  There is a suggested solution at

 http://mail.gnome.org/archives/gtkmm-list/2002-September/msg8.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
___
gtkmm-list mailing list
gtkmm-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtkmm-list


Glib::Dispatcher (multiple emit/write lockup)

2005-06-27 Thread Mario Sergio Fujikawa Ferreira

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.12view=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/msg0.html

which do point out the reentrancy problem.

There is a suggested solution at

http://mail.gnome.org/archives/gtkmm-list/2002-September/msg8.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?

___
gtkmm-list mailing list
gtkmm-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtkmm-list