Re: gtkmm-list Digest, Vol 14, Issue 43
- From: Chris Vine <chris cvine freeserve co uk>
- To: Mario Sergio Fujikawa Ferreira <lioux-list uol com br>
- Cc: gtkmm-list gnome org
- Subject: Re: gtkmm-list Digest, Vol 14, Issue 43
- Date: Sun, 3 Jul 2005 17:41:53 +0100
On Friday 01 July 2005 11:38, Mario Sergio Fujikawa Ferreira wrote:
[snip]
> That does not protect against race conditions. If the
> send_notification (emit()) thread is interrupted right in the middle of
> the write(2) call, we will end up with another thread doing a write(2)
> and another one overlapping is atomicity is not guaranteed. As per the
> POSIX standard upholding, I am not seeing such atomicity guarantees
> under Conectiva Linux 9 kernel 2.4.x series with Linuxthreads. It could
> be just a problem with my development environment (which should not be
> since I am able to reproduce this problem under Mandriva Linux) but we
> should not rely on that but do take a safer approach right from the
> start.
Pipes are, through their file descriptors, a resource shared between processes
as well as threads. You can be pretty sure that glibc is providing the
atomicity guarantees required by POSIX with respect to this, as it tries hard
to get these things right.
You can therefore take it that there is no race condition in relation to
different processes writing to the same pipe. As I said, you are technically
right in the sense that POSIX only guarantees the position where different
processes write to the same pipe, not where different threads within any one
process write to the same pipe. Even if glibc were not to offer atomicity
between threads (although it would have to work hard at not providing
atomicity between threads if it is providing it between processes), I am
pretty certain that this is not your problem (see further below). (It is
difficult to see how interleaved data could cause a lock-up - note that
write() itself is guaranteed to be thread safe.)
[snip]
> Okay, here is my theory from what I gathered from gdb. This is
> just a theory. Others more experienced with {glib,gtk}mm inner workings
> should know better. Well, under some irregular circunstances it is
> possible to lock up all threads (including the main thread and the
> controller thread for that matter) if a send_notification thread is
> preempted in the middle of it's execution while holding the lock. If
> the main/controller thread tries to use the send_notification (emit()),
> it will end up waiting on that mutex. Dead lock. Any way, even if this
> is not the case, I am experienced deadlocks with that approach.
I think I can see where you are going wrong. You should not have the same
thread both (a) calling emit() on the Glib::Dispatcher object (sending the
notification) and (b) being the thread within which the Glib::MainContext
polling the pipe for reading executes (and therefore in which the slot
connected to the Dispatcher executes). You should normally only emit from a
worker thread - ie a thread which is not the main thread (Glib::MainContext)
within which Glib/GTK+ is executing. Otherwise you can get a deadlock.
This deadlock does not arise as you suggest because of a recursive call to any
mutex you use (if all you are doing is putting a mutex around the write call
to the pipe then the same thread which is doing that write cannot at the same
time also be trying to reacquire the mutex), but because the write is a
blocking write and when any one thread is writing to the pipe, it cannot also
be reading from it.
You say you are using the Dispatchers heavily. If you are stuffing so much
data into the pipe that it is full before it has a chance to be read by the
next iteration through the main program loop (Glib::MainContext), then if the
thread sending the notification is also the one which reads from it then it
will block on the write for ever because the pipe can never be emptied.
If you are emitting a signal in the same thread as the one in which you want
the slot connected to it to execute (the main program thread), just use a
plain sigc::signal0<void> object in those cases (reserve the Glib::Dispatcher
for a case where a different thread is sending the notification). You can
have a sigc::signal0<void> object and a Glib::Dispatcher object connected to
the same slot, and because the slot will (if you adopt this approach) be
executing in only the main program thread, you will need no mutexes for it.
Chris.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]