libdbus and edge triggered watches

Nicolas Cavallari Nicolas.Cavallari at lri.fr
Mon May 21 12:58:18 PDT 2012


On 21/05/2012 19:18, Simon McVittie wrote:
> On 21/05/12 13:58, Nicolas Cavallari wrote:
>> Looking at the code, libdbus does not seem to support edge triggered
>> watches. Edge triggered support would essentially mean that libdbus
>> must read()/write() from/to the fd until it returns EAGAIN.
> Correct; it doesn't do that.
>
> Is there any particular reason why you want an edge-triggered watch?
I'm using edge-triggered watches because of boost::asio, which
internally does cross platform edge-triggered io, using epoll in linux.
Boost::asio is more like a proactor design than a reactor one. This is
the kind of library where you just say "Read me 512 bytes" and when it's
done it will call your handler with the 512 bytes in a buffer, ready to
be used. You can also say "Read data until my custom predicate tells me
there is a complete "message" available, then call my handler so i can
parse it", with full threading support. It can also act as a regular
Reactor, so i can still use it for D-Bus, but only with edge triggered
semantics.

I haven't looked, but this is maybe the kind of thing libdbus is already
doing behind the scenes, with the handle_dispatch thing.
>
>> From what i see, the only limitation seems to come from the default
>> value of the max_bytes_{read,written}_per_iteration variables. I think
>> that setting them to an arbitrary high number should be enough to make
>> libdbus work with edge triggered epoll.
> This...
>
>> The alternative would be to call the (wrapped) dbus_watch_handle()
>> repeatedly until the fd is not readable/writable anymore
> ... would essentially be equivalent to this, but inside libdbus.
>
> As far as I'm aware, the reason for the max_bytes_*_per_iteration
> variables is mainly to avoid main loop "starvation": if your process
> sees/produces sufficiently rapid D-Bus traffic that there is always
> something to read/write, then none of your other fds (including,
> perhaps, the one telling you to slow down or exit!) will ever be polled.
>
> Relatedly, it avoids arbitrary memory consumption under extremely heavy
> traffic: if you keep reading from a fd indefinitely, without ever
> pausing to do what libdbus calls "dispatching" (sending in-memory
> messages to their consumers), and there's always another message to
> read, then the messages will be queued in memory forever, and will never
> actually be dispatched to their consumers and (hopefully) freed.
I am already dispatching inside the busy read loop, mostly as a hack
because of limitations of dbus-c++ bindings.
But can't that be fixed by using threads to perform the reads, and
concurrently dispatching them in the "main" thread ? The kind of things
that asio does.
> or wrap an edge-triggered
> epoll in a higher-level construct that remembers that the D-Bus socket
> is still readable/writeable and interleaves reads/writes/dispatching
> with polling other sockets (with the timeout set to zero for as long as
> you know reads/writes are pending).
I think i will just replace my busy read hack with your suggestion. That
should even be easier to do with boost::asio.

Thanks for the pointers.


More information about the dbus mailing list