Image of Linux Kernel Development (3rd Edition)
Image of Android Wireless Application Development
Image of Modern Operating Systems (3rd Edition)
Image of Operating System Concepts

Monitoring D-Bus

Because D-Bus operates for the most part under the hood invisible to the user, means of monitoring D-Bus messages is important for both activation and debugging purposes.  In this post I examine how to monitor and act on such messages.  I assume that you are relatively familiar with D-Bus. If not, you should look at my previous posts on D-Bus to gain an understanding of the basic concepts.

Probably the most commonly used tool is the command line utility dbus-monitor which was written by Philip Blundell as part of the reference D-Bus implementation and which is standard on most D-Bus enabled platforms.  It is a very powerful utility but unfortunately it’s man page is terse and fails to explain the most powerful feature of dbus-monitor i.e. watch expressions.

Suppose, for example, I want to monitor the creation, saving and deletion of Tomboy notes using D-Bus signals. To get the list of the supported signals I could introspect Tomboy using qdbus e.g.

$ qdbus org.gnome.Tomboy /org/gnome/Tomboy/RemoteControl | grep signal
signal void org.gnome.Tomboy.RemoteControl.NoteAdded(QString uri)
signal void org.gnome.Tomboy.RemoteControl.NoteDeleted(QString uri, QString title)
signal void org.gnome.Tomboy.RemoteControl.NoteSaved(QString uri)

or I could use dbus-monitor to look at the signals generated when Tomboy creates, saves and deletes a note.

$ dbus-monitor type=signal interface="org.gnome.Tomboy.RemoteControl"
signal sender=org.freedesktop.DBus -> dest=:1.102 path=/org/freedesktop/DBus;      interface=org.freedesktop.DBus; member=NameAcquired  string ":1.102"
signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteAdded
   string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"
signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteSaved
   string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"
signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteDeleted
   string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"
   string "New Note 1"

As you can see Tomboy issues three signals – NoteAdded when a note is added, NoteSaved when a note is saved, and NoteDeleted when a note is deleted.  Interestingly, for some reason NoteDeleted provides both the uri and the title of the note whereas the other two signals only provide the uri.

Suppose I just want to to monitor when a Tomboy note is saved by a user.  I can use a dbus-monitor watch expression for this purpose as shown in the following example.

dbus-monitor "type='signal',sender='org.gnome.Tomboy',interface='org.gnome.Tomboy.RemoteControl',path='/org/gnome/Tomboy/RemoteControl',member='NoteSaved'"

A watch expression is essentially a message filter.  Note the syntax!  Everything between the two double quotes is part of the watch expression.

Unfortunately the syntax of a watch expression is not documented in the dbus-monitor man page.  However from looking at the source code for dbus-monitor, it appears that a watch expression consists of one or more name-value pairs, e.g. sender=’org.gnome.Tomboy’ separated by commas.  The following are valid names: type, sender, destination, path, interface, member and error_name.  The value of type must be one of the following: signal, method_call, method_return or error

Probably the most powerful feature of dbus-monitor is the fact that you are not limited to using just one watch expression at a time.  The following example simultaneously monitors all 3 Tomboy signals and uses awk to parse the output from dbus-monitor and display a meaningful message.



WATCH1="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteAdded'"
WATCH2="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteSaved'"
WATCH3="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteDeleted'"

dbus-monitor "${WATCH1}" "${WATCH2}" "${WATCH3}" | \
awk '
/member=NoteAdded/ { getline; print "Created note " substr($2,7) }
/member=NoteSaved/ { getline; print "Added note " substr($2,7) }
/member=NoteDeleted/ { getline; print "Deleted note " substr($2,7) }

Here is the output generated when I clicked on the Tomboy icon to create a new note, waited for the automatic save and then selected the delete option to delete the note.

$ ./test
Created note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"
Added note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"
Deleted note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"

Well that is all for this post. Enjoy!

P.S. All of the above examples were tested on Fedora 10. I have no idea whether they will work on other Linux distributions or versions of Fedora.

Comments are closed.