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