Simplest mainloop that could possibly work
Havoc Pennington
hp at redhat.com
Tue Oct 30 12:13:17 PDT 2007
Hi,
Andrew Clunis wrote:
> I had originally intended to use dbus_connection_read_write_dispatch()
> function, and have the other thread call
> dbus_connection_send()/dbus_connection_flush(). Of course, that's no
> good because dbus_connection_read_write_dispatch() blocks on read I/O.
> Thus, rather comically, the messages for transmission get buffered and
> are only sent once the service happens to *receive* a message.
This is probably a bug - there should be a wakeup to the
read_write_dispatch when you send a message. I think someone may have
posted a patch for it even, or at least there was a past thread
discussing how to do the patch. Maybe I'm thinking of something in
bugzilla. Anyway... you may find it's easier to fix this than do your
own loop.
> So, it looks like I have to bite the bullet and write a non-toy
> mainloop. I'm having a lot of trouble grokking the Watch/Timeout stuff,
> though, and I haven't had much luck finding useful example code.
>
> As far as I understand it, I'm supposed to call
> dbus_connection_set_watch_functions() and
> dbus_connection_set_timeout_functions(). I'm unclear as to what I
> should do once I have a poll() loop running on the FDs, however.
Some example code you could use is:
- GLib bindings / main loop
- Qt bindings / main loop
- the main loop used by the bus daemon (which is in
dbus/dbus-mainloop.c)
What you need to be clear on is what read, write, and dispatch mean.
That is,
- read from socket into buffer (add to incoming message queue)
- write out buffer to socket (drain outgoing message queue)
- dispatch (run handlers to drain incoming message queue)
Anytime there is data for reading or a timeout on the poll(), there may
be changes to the incoming message queue. A timeout could e.g. add a
timeout error message to the queue.
So, anytime you read, you need to dispatch (or at least check the
dispatch status) in case there's stuff to dispatch.
When there is stuff in the outgoing queue, you'll have a write watch and
will need to poll so you wake up when the socket is ready for writing.
Blocking happens whenever there's nothing to dispatch, and the socket
has nothing to read, and we either have nothing to write or the socket
is not ready for writing.
When threads are involved you also need a "wakeup main function" which
solves the problem you are seeing with read_write_dispatch, i.e. if the
main loop is blocking and another thread adds to the outgoing queue, the
main loop has to be kicked out of the poll().
This is in no way trivial - it is definitely less work to fix the
read_write_dispatch issue.
Another option is to try to use some main loop library (libevent? though
I haven't tried that one myself), or cut-and-paste from something like GLib.
Havoc
More information about the dbus
mailing list