Tag Archives: D-Bus

Tip for debugging refcounting issues: change ref calls to copy

Over the last couple of days I’ve been looking at a refcounting issue in GLib’s D-Bus implementation.

As with many things in GLib, the allocations in this code use refcounting, rather than new/free, to manage object lifecycles. This makes it quite hard to debug lifecycle issues, because the location of a bug (a ref or unref call which isn’t correct) can be quite far removed (in time and code) from where the effects of that bug become visible. This is because the effects of refcounting problems only become visible when an object’s refcount reaches zero, or when the program ends and its refcount still hasn’t reached zero.

While debugging this code, I tried an approach I haven’t before: changing some of the ref calls on the buggy object to be copy calls instead. (Specifically, changing g_object_ref() to g_dbus_message_copy().) That split up the lifecycle of the object into smaller pieces, narrowing down the sets of ref/unref calls which could be buggy. Ultimately, this allowed me to find some bugs in the code, and hopefully those are the bugs causing the refcounting issue. Since the issue is intermittent, it’s a bit hard to be sure.

This debugging approach was possible in this case because the object I was debugging is immutable, so passing around copies of it doesn’t affect the behaviour of other bits of code vs passing around the original. Hence this approach is only applicable in some situations. But it’s another good reason why using immutable objects is quite helpful when writing code, and it’s certainly an approach I’m going to be using again when I can.

Testing D-Bus clients with libglib-testing

I’ve always found it a bit of a pain to write unit tests for D-Bus client libraries, where you’re testing that your code calls methods on a D-Bus service appropriately and, in particular, correctly handles a variety of return values and errors. Writing unit tests like this traditionally involves writing a mock D-Bus service for them to talk to, which validates the input it receives and provides appropriate responses. That often goes most of the way towards reimplementing the entirety of the real D-Bus service.

Part of the difficulty of testing D-Bus clients like this is synchronising the state of the mock D-Bus service with the test code, and part of the difficulty is the fact that you have to write mock service code for each D-Bus method before you can test it — which is a lot of investment in writing code before you can even start writing your unit tests themselves.

As an experiment in finding a better way of doing this kind of testing, I’ve written GtDBusQueue in libglib-testing, and I think it might be ready for some wider use. Thanks a lot to Endless for allowing me to work on such projects! I’ve used it in a couple of projects now, particularly in libmalcontent (which handles implementing parental controls policy on the desktop, and needs to talk to the accountsservice D-Bus service).

GtDBusQueue basically implements a queue for D-Bus messages received from your D-Bus client code. Each D-Bus message is typically a method call: your unit test can inspect the queue, and will typically pop messages off the front of the queue to assert they match a certain method call, and then send a reply to that call.

A key feature of GtDBusQueue is that it operates as a queue of D-Bus messages, rather than as a collection of D-Bus object proxies (typically GDBusObjectProxy), which means that it can be used to handle method calls to arbitrary D-Bus object paths without having to implement a new proxy class for each of them.

Message matching is typically implemented using gt_dbus_queue_assert_pop_message() (though other methods are available which give you finer-grained control over message matching and removal from the queue). It blocks until the queue is not empty, pops the first message off the front, asserts that its D-Bus object path, interface name and method name are as expected, and then returns the method call parameters to your unit test code using the same syntax as g_variant_get(). Your unit test code can then check the values of those parameters how it pleases.

If your D-Bus client code is asynchronous, GtDBusQueue can be used inline in your unit test. Your client code will start a method call asynchronously, then the test code will pop the method call off the GtDBusQueue, check it and reply, and then your client code will asynchronously finish its method call and handle the results. You can see an example of this in the test_app_filter_bus_get_error_disabled() test in libmalcontent which, in a single function, tests that the mct_manager_get_app_filter_async() API can correctly handle a D-Bus InvalidArgs error returned by the second D-Bus call it makes.

If your D-Bus client code is synchronous, GtDBusQueue needs to run in a thread using gt_dbus_queue_set_server_func(), since otherwise it would block your D-Bus client code. The unit test and the server thread take turns at blocking on pushing messages onto the queue or popping them off. You can see an example of this (which also works for asynchronous client code, testing both the synchronous and asynchronous code paths in a single test) in the GtDBusQueue usage example in its documentation.

That’s a brief introduction to GtDBusQueue; hopefully it’s given you a bit of an idea about where it’s appropriate and how it can be used. There’s documentation in the source code (including some usage examples), and a load of usage examples in libmalcontent. Feedback, questions and improvements are always welcome!

Automatically shutting down a daemon on inactivity

tl;dr: Use gss_service_hold() and gss_service_release() from libgsystemservice.

Automatically shutting down daemons when not in use is in vogue, and a good way of saving resources quite easily (if the service’s startup/shutdown costs are low).

libgsystemservice can do this for you automatically, if your code is based on GssService, or if you want to port over to it (which should be fairly straightforward for simple services). It supports inactivity timeouts by default; just call gss_service_hold() when you start doing some activity, and gss_service_release() when you stop.

(Also, look, it’s neat that you can generate documentation and automatically publish it from your master branch using GitLab CI!)

libgsystemservice: a library for writing D-Bus system services

Having written a few D-Bus system services recently, it felt like I was cargo-culting the same bits of code in all of them. I’ve split some of that out into a new library, libgsystemservice, which I hope will grow to contain all the bits people need to write D-Bus system services and other system daemons.

At the moment, it includes a way to load configuration files from multiple directories (with /etc taking priority over /usr/share, for example); tracking of D-Bus peers which have interacted with your service, and their credentials; and an equivalent of GApplication for system services. (GApplication only works on the session bus, and has various features targetting user applications which aren’t appropriate for system services.)

We’re using this code within Endless at the moment; but the more users it has, the better. Feedback and contributions are very welcome on GNOME’s GitLab.

GUADEC 2017: sun, rain, Coverity, walks

GUADEC 2017 has ended in Manchester. It’s been great; thanks to the organisers and sponsors for a fun conference (this year’s highlight: a preponderance of Tiki bars).

We’ve had sun and heat, and we’ve had rain and more rain. Often within the same hour. On the final day of the conference, a group of us went out to Edale to do some walks to see the Peak District, a national park area near Manchester. This is an area I’ve visited many times before, so it was fun to be able to show it to GNOME people.

This year I gave a talk about the Coverity scans I’ve been running on various GNOME and freedesktop modules for the last year. The slides are online and the video will be up with the rest of the GUADEC videos. If you have a security-critical (or other) module which you’d like to be included in the scan set, let me know. Coverity’s good at finding bugs in complex control flows, but you do need to put some time into triaging its reports. I’m happy to provide guidance about using it.

I spent a fair amount of time during the unconference days reviewing Simon McVittie’s D-Bus work to add support for app-containers into the D-Bus specification and dbus-daemon. This is the first part of an effort to improve support for exposing unconfined D-Bus services to confined app-containers safely and efficiently. The rest of my time was spent working on exciting support for updating flatpak over the LAN for Endless OS. I’ll blog about this more in future.

Thanks to the GUADEC team for organising a great conference, the conference sponsors, and to my employer, Endless, for sponsoring me to go.

Checking D-Bus API stability

Announcing dbus-deviation, a small tool and set of libraries for automatically checking whether a D-Bus interface has broken API between two releases of a piece of software, developed as part of my work at Collabora.

Why?

If you have a large software project, worked on by multiple developers, it might not be clear when D-Bus interfaces change. For example, they might be pulled in from another repository, or might be accidentally changed without anyone noticing.

Breaks in the D-Bus API of a project (when it’s supposed to be stable) are potentially worse than breaks in its C API, because they can only be detected at runtime — when client applications suddenly error out half-way through an operation because they’ve called a D-Bus method with the wrong argument type. At least with C API breaks, the compiler will catch the break.

(In this respect, I guess D-Bus APIs are actually a form of ABI — a runtime interface, rather than a compile-time interface.)

How?

dbus-deviation provides a utility called dbus-interface-diff, plus some GNU Make glue to plug it into your build system. It only works with git: for each tagged release of your project, it uses git-notes to store copies of all the D-Bus interfaces you care about, in their state at the time of that release. They’re stored as introspection XML; if you have that XML committed into the repository anyway, the git-note becomes a ref to the existing file blob, and takes up virtually no space at all. The dbus-interface-diff tool then does a diff between two XML files (for example, one stored for the most recent release, and the one currently in your working tree), and flags up any forwards- or backwards-incompatibilities.

What?

A backwards-incompatibility, as far as dbus-deviation is concerned, is one where existing clients will not work against new versions of the D-Bus service, for example because a method they use has been removed.

A forwards-incompatibility is one where new versions of clients may not work against old versions of the D-Bus service, for example because they use a method which has been added in a new version of the API.

Traditionally, projects care about preventing backwards-incompatible API changes, and don’t care so much about forwards-incompatibilities. dbus-deviation lets you set your desired stability policy.

Where?

dbus-deviation has a spartan website, a git repository, and bugs are stored using Bugs Everywhere in git; contact me in the comments or by e-mail if you want to report something. API documentation is available for the Python libraries underpinning it, which provide an AST and diff methods for D-Bus APIs.

To get using it, follow the instructions in the README file!

All feedback is very much welcome. One area I feel is still a little awkward is how dbus-deviation integrates with make dist — it forces use of a pre-push git hook to update the remote git-notes for the API signatures of newly pushed release tags. That needs to be set up by each developer who releases a project (using make dist) — any suggestions for improving this are welcome.

What next?

API stability checking for GIR APIs, perhaps? This one needs some more work.

D-Bus API design guidelines

D-Bus has just gained some upstream guidelines on how to write APIs which best use its features and follow its conventions. Hopefully they draw together all the best practices from the various articles which have been published about writing D-Bus APIs in the past. If anybody has suggestions, criticism or feedback about them, or ideas for extra guidelines to include, please get in touch!

All aboard the Bendy Bus

Have you ever written a client for a D-Bus service, then had difficulty in testing it because you need to find a way to set up the state of the D-Bus service, run your test, then set up the service in a completely different manner, rinse and repeat…all while running a modified version of the service’s binary in parallel with your system installation of it, and without doing anything which might cause your personal data to be accidentally eaten?

Having done some hacking on Telepathy and EDS clients I can, unfortunately, say “yes” to all of the above. Since problems are problematic, I’ve been hacking on a tool called Bendy Bus, which will hopefully alleviate some of this pain.

Bendy Bus is a project I’ve been working on as my final year university project, but I intend for it to be most useful outside of (hopefully) getting me marks for my degree. The basic idea of Bendy Bus is that you fuel it up with a description of a nondeterministic finite state automaton which represents the D-Bus service you’re using, plus a D-Bus introspection XML file describing all the relevant D-Bus interfaces. Bendy Bus will use the FSM description to simulate the D-Bus service, and run as a wrapper around the client program you’re trying to test. It’ll set up a private dbus-daemon instance for your client program, and expose all the simulated D-Bus objects on this bus.

Bendy Bus will listen for D-Bus method calls and property changes made by your client program, and execute transitions within the FSM as coded in your FSM description file. These transitions may, for example, change the FSM’s state, change data stored in the FSM (technically making it a nondeterministic DFSM, but that’s immaterial), emit D-Bus signals, throw D-Bus errors, etc. Why do I say it’s a nondeterministic FSM? Because you may specify several transitions between the same pair of states which are triggered by the same (for example) D-Bus method call. Bendy Bus will randomly choose one of the transitions to take. For example, if your client program calls a frobnicate : string → string D-Bus method, you could code one transition which successfully replies to the method call with a string return value, and another transition which simulates a failure in the D-Bus service by throwing a D-Bus error instead.

It’s in this fashion that Bendy Bus is actually designed as a fuzzing tool. You can code up a full description of every possible state and transition in your D-Bus service, then set your client program running in the Bendy Bus wrapper, and it’ll randomly explore the service’s state space until a termination condition is met. For example, the client program could crash (in which case a bug’s been found!), a D-Bus activity timeout could be reached (if your client program hasn’t made any D-Bus calls for a few seconds, for example), or a global timeout could be reached. At this point, the test harness can restart your client program and start the whole thing all over again with a different random seed value, causing different execution paths to be explored, and more of your client’s code to be covered.

Of course, Bendy Bus is still young, so features are missing, there are plenty of bugs, and documentation is basically non-existent. A couple of the big features on the list are to implement support for unit testing (which would tone down the fuzz testing aspect of Bendy Bus, and allow deterministic unit tests to be written for D-Bus client programs), implement better error reporting in the machine description parser and better logging during simulation, write a language specification and GtkSourceView highlighter, and write documentation. Help on any of these (except the unit testing stuff, which I have to keep for myself for my university project) would be greatly appreciated.

More than anything, it would be great if people could play with Bendy Bus and see if it’s useful for them (and if not, what could be done to improve it). In the repository at the moment are a couple of example machine description files for Telepathy. They can be used to get a randomly-generated contact list to appear in Empathy, using the following command:

bendy-bus machines/telepathy-cm.machine machines/telepathy-cm.xml \
--test-program-log-file=test-program.log \
--dbus-daemon-log-file=dbus-daemon.log \
--simulator-log-file=simulator.log \
-E FOLKS_DEBUG=telepathy -E EMPATHY_DEBUG=all -E G_MESSAGES_DEBUG=all \
-- empathy

That’s all from me at the moment. The Bendy Bus git repository is on gitorious, and all bug reports should be e-mailed to me: philip {at} tecnocode.co(.)uk.