DBus is a concept of software bus, an inter-process communication (IPC), and a remote procedure call (RPC) mechanism that allows communication between multiple computer programs (that is, processes) concurrently running on the same machine. DBus was developed as part of the freedesktop.org project, initiated by Havoc Pennington from Red Hat to standardize services provided by Linux desktop environments such as GNOME and KDE.
In this post, we only talk about how does DBus daemon run and how KDE Applications/Frameworks connect to it. For more details of DBus itself, please move to DBus Wiki.
There are two types of bus:
session bus and
system bus. The user-end applications should use
session bus for IPC or RPC.
For the DBus connection, there is already a good enough library named QDBus provided by Qt. Qt framework and especially QDBus is widely used in KDE Applications and Frameworks on Linux.
A mostly used function is
QDBusConnection::sessionBus() to establish a connection to default session DBus. All DBus connection are established through this function.
Its implementation is:
_q_manager is an instance of
QDBusConnectionManager is a private class so that we don’t know what exactly happens in the implementation.
The code can be found in qtbase.
On macOS, we don’t have a pre-installed dbus. When we compile it from source code, or install it from HomeBrew or somewhere, a configuration file
session.conf and a
launchd configuration file
org.freedesktop.dbus-session.plist are delivered and expected to install into the system.
session.conf, one important thing is
<listen>launchd:env=DBUS_LAUNCHD_SESSION_BUS_SOCKET</listen>, which means socket path should be provided by
launchd through the environment
launchd is a unified operating system service management framework, starts, stops and manages daemons, applications, processes, and scripts. Just like
systemd on Linux.
org.freedesktop.dbus-session.plist describes how
launchd can find a daemon executable, the arguments to launch it, and the socket to communicate after launching daemon.
Once the daemon is successfully launched by
launchd, the socket will be provided in
DBUS_LAUNCHD_SESSION_BUS_SOCKET env of
We can get it with following command:
launchctl getenv DBUS_LAUNCHD_SESSION_BUS_SOCKET
KDE Connect needs urgently DBus to make, the communication between
kdeconnect-indicator or other components, possible.
Currently, we delivered
dbus-daemon in the package, and run
./Contents/MacOS/dbus-daemon --config-file=./Contents/Resources/dbus-1/session.conf --print-address --nofork --address=unix:tmpdir=/tmp
--address=unix:tmpdir=/tmp provides a base directory to store a random unix socket descriptor. So we could have serveral instances at the same time, with different addresse.
--print-address can let
dbus-daemon write its generated, real address into standard output.
Then we redirect the output of
KdeConnectConfig::instance()->privateDBusAddressPath(). Normally, it should be
$HOME/Library/Preferences/kdeconnect/private_dbus_address. For example, the address in it is
Therefore, our program can access this file to get the real DBus address, and use another function in QDBus to connect to it:
We redirect all
QDBusConnection::connectToBus to connect to our own DBus.
With such solution,
kdeconnect-indicator coworks well. But in KFrameworks, there are lots of components which are using
QDBusConnection::sessionBus rather than
QDBusConnection::connectToBus. We cannot change all of them.
Then I came up with an idea, try to fake a session bus on macOS.
To hack and validate, I tried to launch a
/tmp/dbus-K0TrkEKiEB as address, and then I tried type this in my terminal:
launchctl setenv DBUS_LAUNCHD_SESSION_BUS_SOCKET /tmp/dbus-K0TrkEKiEB
Then I launched
dbus-monitor --session. It did connect to the bus that I launched.
And then, any
QDBusConnection::sessionBus can establish a stable connection to the faked session bus. So components in KFramework can use the same session bus as well.
To implement it in KDE Connect, after starting
dbus-daemon, I read the file content, filter the socket address, and call
launchctl to set
// Set launchctl env
Then everything works!
- Since we can directly use session bus, the redirect from
QDBusConnection::connectToBusis not necessary anymore. Everyone can connect it in convenience.
- Each time we launch
kdeconnectd, a new
dbus-daemonis launched and the environment in
launchctlis overwritten. To improve this, we might detect whether there is already an available
dbus-daemonthrough testing connectivity of returned
QDBusConnection::sessionBus. This might be done by a bootstrap script.
- It will be really nice if we can have a unified way for all KDE Applications on macOS.
I’m looking forward to a general DBus solution for all KDE applications :)