Re: [Dbus-cxx-devel] Some 'sent' messages don't get sent
Status: Beta
Brought to you by:
rvinyard
From: Patrick A. <pa...@ph...> - 2009-08-28 20:39:51
|
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 |