Race condition when using dbus_connection_send() from multiple threads sharing the same connection
Tom Hughes
Tom.Hughes at palm.com
Thu Sep 17 10:33:38 PDT 2009
Hello,
A similar message was posted earlier this month with the title "[Dbus-
cxx-devel] Some 'sent' messages don't get sent". The author suggested
that there is a bug in D-bus and he was referred to the general
"threads bug" here: https://bugs.freedesktop.org/show_bug.cgi?id=857 .
The issue hasn't been added to that bug and the other issues discussed
in the bug don't appear related to this issue.
I've encountered the exact same issue that was described and came to
the exact same conclusion as the original poster.
The problem can occur when multiple threads are sharing the same
DBusConnection and sending messages with dbus_connection_send(). This
ends up calling _dbus_connection_do_iteration_unlocked(), which calls
_dbus_connection_acquire_io_path(). With multiple threads sending at
the same time, it's possible for _dbus_connection_acquire_io_path() to
fail because the other thread has acquired the I/O path. In that case
_dbus_transport_do_iteration() is not called, and that function is the
one that leads to check_write_watch() being called in
socket_do_iteration() in order to notify the mainloop that there is a
message pending. As a result, the message is in the outgoing queue,
but is essentially stuck and won't be sent until the next call to
dbus_connection_send().
Unfortunately, since check_write_watch() uses the DBusTransport, it
appears to require that the io mutex be held, so we can't simply call
check_write_watch() in the failure path.
Another option might be to change the following line in
_dbus_connection_do_iteration_unlocked() from:
if (_dbus_connection_acquire_io_path (connection,
(flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
to:
if (_dbus_connection_acquire_io_path (connection,
(flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : -1))
That would force the second thread that can't acquire the io path to
wait until it can, but that appears to break the asynchronous
semantics of _dbus_connection_send().
Thoughts?
Tom
More information about the dbus
mailing list