[Fwd: Re: [Dbus-cxx-devel] Some 'sent' messages don't get sent]

Rick L. Vinyard, Jr. rvinyard at cs.nmsu.edu
Tue Sep 1 09:20:45 PDT 2009


---------------------------- Original Message ----------------------------
Subject: Re: [Dbus-cxx-devel] Some 'sent' messages don't get sent
From:    "Patrick Allison" <patrick at phys.hawaii.edu>
Date:    Fri, August 28, 2009 2:39 pm
To:      dbus-cxx-devel at lists.sourceforge.net
--------------------------------------------------------------------------

Hi again:

Sorry for the flurry of messages (OK, two is not a flurry), but I did a
bit more debugging staring around at code. I think the problem's a race
condition between the watch thread and the dispatch thread (and I really
hope this isn't just some bug in my version of D-Bus, but I didn't see
anything like it in the bugzilla for D-Bus).

>From what I can see, the problem is that:
1) a request comes in, which wakes the watch thread, and calls
dbus_handle_watch.

2) This calls "_dbus_connection_acquire_io_path" in
_dbus_connection_handle_watch, which locks the I/O path.

3) While the I/O path is held, _dbus_connection_handle_watch calls
_dbus_transport_handle_watch, which reads the message, and calls
_dbus_connection_queue_received_message_link.

4) _dbus_connection_queue_received_message_link calls
_dbus_connection_wakeup_mainloop, which wakes the dispatch thread. NOTE:
I have no idea why _dbus_connection_queue_received_message_link does this.
I don't believe it should - it has no reason to wake up the main loop. The
watch handler, when it's done, should wake the main loop by changing the
dispatch status.

5) The dispatch thread wakes up, grabs the data, dispatches it, calls the
function. That function returns a value, which causes Connection::send to
be called, which calls dbus_connection_send.

6) dbus_connection_send calls _dbus_connection_acquire_io_path, which
fails (since it's still being held in the watch thread!) and the message
quietly gets queued without anyone knowing that it needs to be.

To me, this looks like a bug in D-Bus: if _dbus_connection_acquire_io_path
fails during a write, it should enable the write watch if it's disabled:
this might seem silly, as select() will immediately say "writeable", but
the write watch shouldn't care *why* a write got queued, only that it did
and it needs to be handled when the application gets a chance.

A (bad) workaround in dbus-cxx would be a mutex preventing messages from
being dispatched while in the read handler in the watch thread.

Patrick





More information about the dbus mailing list