dbus_connection_send IO path acquire failure issue

Patrick Allison patrick at phys.hawaii.edu
Tue Mar 2 15:47:14 PST 2010


Hi all:

I'm trying to see if anyone's noticed or thought about bug #23584
( https://bugs.freedesktop.org/show_bug.cgi?id=23584 ) -
"dbus_connection_send should check to install write watch if pending
messages remain"

I haven't seen any activity or mention of it since September, and while
I've been looking through the D-Bus code I can't think of an easy way to
fix it.

The summary is this:

dbus_connection_send can fail to send a message in 2 different ways:
first, if the socket is not writable, and second, if the IO path is not
acquirable. The first is handled fine - a write watch is enabled, and
the main loop then knows to wait and see if a socket becomes writable.

The second is not handled at all. You can see this in
_dbus_connection_do_iteration_unlocked : nothing happens if the IO path
is not acquirable. No write watch is set, nothing. Then, all that
happens is dbus_connection_send() wakes up the main loop, but since no
write watch is enabled and the dispatch status is unchanged, the main
loop has no idea it needs to do anything. The message simply sits until
a different message is sent, which could be much later. 

I don't see how this could be called a 'main loop problem' because I
don't know what the main loop is supposed to do in this case. I guess it
could call dbus_connection_flush() if there are messages pending and the
write watch is disabled, but this seems incorrect, because if the socket
is unwritable at the moment, it'll block the main loop until it is, when
all you really wanted to do was enable the write watch to be able to
select()/poll() on it.

This can happen pretty easily in the dbus-cxx bindings, which uses
separate threads for watch handling and dispatching. However, I'm pretty
sure it can happen in any threaded program, since it will simply happen
anytime dbus_connection_send is called with the IO path lock held.

I'm really not sure the best way to fix this, because I'm not sure what
the "IO path" really defines - is it intended to protect just the file
descriptor itself, or the file descriptor + DBusTransport structures
describing it, or something else? If it's just the file descriptor, then
it would probably make sense to add a function in dbus-transport.h which
enables the write watch directly.

The other possibility is to have dbus_connection_send block until the
I/O path is acquirable. The documentation says that it doesn't block to
send to network, so that would still be true. That might be the best
thing to do, because I don't think any thread would hold the IO path
indefinitely.

Ideas/comments? The bug listed above has a debug trace of the bug
happening. The bug was found with dbus-1.2.16, but it's still there with
dbus-1.2.20.

Thanks,
Patrick



More information about the dbus mailing list