Bug 23584 - dbus_connection_send should check to install write watch if pending messages remain
Summary: dbus_connection_send should check to install write watch if pending messages ...
Status: RESOLVED MOVED
Alias: None
Product: dbus
Classification: Unclassified
Component: core (show other bugs)
Version: 1.5
Hardware: All All
: medium normal
Assignee: D-Bus Maintainers
QA Contact: D-Bus Maintainers
URL:
Whiteboard: threads
Keywords:
Depends on:
Blocks:
 
Reported: 2009-08-28 14:16 UTC by Patrick Allison
Modified: 2018-10-12 21:05 UTC (History)
2 users (show)

See Also:
i915 platform:
i915 features:


Attachments
Process log with DBUS_VERBOSE set showing missed sent message (7.27 KB, text/plain)
2009-08-28 14:16 UTC, Patrick Allison
Details

Description Patrick Allison 2009-08-28 14:16:47 UTC
Created attachment 28990 [details]
Process log with DBUS_VERBOSE set showing missed sent message

dbus_connection_send currently only wakes the main loop if there are remaining messages (connection->n_outgoing > 0). However, there are *two* ways for messages to still be remaining: 1) if the socket was not immediately writable, or 2) if the IO path was not acquirable. If 1), the transport installs the write watch, but if 2), the write watch is not installed, and while the main loop wakes up, it won't attempt to handle the write watch, and the messages won't get sent.

This can happen if the dispatch loop and the read/write loop are in different threads: the read watch handler is called, which processes data, and queues the message - this wakes the mainloop (because _dbus_connection_queue_message_link wakes the mainloop) which dispatches the message. The dispatched message gets a reply, which sends dbus_connection_send, all before the read handler ever finishes (and thus before the IO path is released).

The message is then queued for sending, but no write watch is installed, and so the message will just sit there, possibly for very long.

I'm attaching the output of a process where this happened with DBUS_VERBOSE (and PTHREAD_IN_VERBOSE) set. The log begins when the process calls dbus_watch_handle on the read watch. You can see the main thread being woken, the dispatch handling, and the send occurring in the other thread before dbus_watch_handle releases the IO path. The main loop is woken up since there are still messages to send, but has nothing to do: the write watch is disabled, and the dispatch status is complete.

Note that this process was using the dbus-cxx D-Bus bindings, which uses two separate threads for dispatching and watching read/write fds. It also was using dbus-1.2.16, but I believe the problem is still present in the 1.3 branch.
Comment 1 Simon McVittie 2014-09-10 17:04:19 UTC
(In reply to comment #0)
> Note that this process was using the dbus-cxx D-Bus bindings, which uses two
> separate threads for dispatching and watching read/write fds.

Well, that's alarming. I haven't previously encountered anyone splitting libdbus' I/O between two threads like that.

In practice, I don't think anything except

- provide functions to hook up timeouts
- provide functions to hook up watches
- dispatch those, and call their associated functions, in one thread that
  is running a select(), poll() etc. loop

is going to work very well. dbus/dbus-mainloop.c and associated files are one example of an implementation.
Comment 2 GitLab Migration User 2018-10-12 21:05:56 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/dbus/dbus/issues/19.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.