Demand starting per-user Desktop Bus user services

Desktop Bus servers communicate with clients via an intermediary "broker" process, which passes messages around and keeps track of registered server "names". Clients generally rely upon servers either being explicitly run or started on demand. The old way of demand-starting servers, on systems without per-user service managers, was for the broker process to directly spawn the server processes. This so-called "bus activation" should be avoided on systems with service management, for several reasons. On systems with per-user service managers, the per-user service manager has a definition of the Desktop Bus server and either the broker process tells the service manager when to start it or the user explicitly enables the service to start automatically at startup using the normal service manager mechanisms. Or both.

How it works

Demand start of per-user Desktop Bus servers works like this:

  1. A Desktop Bus client contacts the broker and asks it to connect it to the server org.example.Sheila.

  2. Recognizing that no server by that name has yet been registered with it, the Desktop Bus broker scans its server definition files for a server that has Name=org.example.Sheila. These files include the overrides at ~username/.local/share/dbus-1/services.

  3. It finds an override named ~username/.local/share/dbus-1/services/org.example.Sheila.service that has Name=org.example.Sheila.

  4. Using dbus-daemon-launch-helper, the broker sends a system-control --user start org.example.Sheila to the per-user service manager.

  5. The per-user service manager starts the ~username/.config/service-bundles/services/org.example.Sheila service.

  6. The service contacts the Desktop Bus broker (whose address it knows from the DBUS_SESSION_BUS_ADDRESS environment variable that the service is configured with) and registers the org.example.Sheila service.

  7. The broker finally answers the connection request from the original client.

Unified server names

In theory dbus-daemon-launch-helper is supposed to look in the Desktop Bus broker server definition file for a SystemdService setting. In theory, the name of the service to be started could thus be different from the name that the server registers with the broker when it starts up.

Moreover: Originally, the Name field in a server definition file could differ from the name of the server definition file itself, too. So there would be three names, all different: the name of the server definition file, the Name field within it, and the service management service name named by the SystemdService named within it.

But the Desktop Bus people discovered that this made it far too easy to mess things up in various surprising ways, and nowadays they try to enforce the convention that the Name is always the same as the server definition filename. Adhering to this convention prevents, for one thing, the ambiguous case of two (or more) server definition files with different names that define the same server Name internally. The broker actually does not guarantee which server definition file it picks in such a scenario. If the server definition file name is always the server registration name, installation and package managers will notice the filename conflict.

The same reasoning applies to the SystemdService setting, the name seen by the service manager. It is far too easy to mess things up in various surprising ways if the names used in service management do not match the server names seen by the broker. In practice, this is pointless extra indirection. And the systemd people quickly adopted the convention that if the registration name is not the service management name itself, the service management name must have the registration name as an alias, so that the service can be managed using its registration name.

dbus-daemon-launch-helper thus adopts the convention that the service name given by SystemdService, the registration name given by Name, and the name of the Desktop Bus server definition file, are all the same single name. The broker gives the helper the name of the server definition file, so it just uses that as-is, and entirely ignores the server definition file contents and its superfluous, pointless, and problem-enabling Name and SystemdService fields.

Creating more demand-started services of your own

To create your own demand-start Desktop Bus server process, you need to create a user-level service bundle (in ~/.config/service-bundles/services) for your per-user service manager and a override server definition file for the Desktop Bus broker. Proceed as follows:

  1. Find the old server definition file for it. This will be somewhere in /usr/local/share/dbus-1/services, or its equivalent.

  2. Make a note of the Exec setting in that file. This will be how your service bundle starts the service.

  3. Make a note of the Name setting in that file. This will be the single unified name of everything.

  4. Create a file with that name (plus .service) in your personal server definitions directory as ~/.local/share/dbus-1/services/name.service. Do not worry if it is a different name to the server definition that it is overriding. Ironically, one of the complex mechanisms that it makes it so easy to mess things up is the system where the broker "knows" that two differently named files actually define the same server. Usually it will be the same name, though, per the modern Desktop Bus naming convention that tries to avoid the mess; and as long as there are just the two files, one in your personal server definitions directory and one in the system-wide (user) server definitions directory, the broker's "directory priority" scheme comes into play and there is no ambiguity.

  5. The file is a Windows INI file. Its contents should comprise a [D-BUS Service] section with fields as follows:

    It has to contain User=something, even though the broker is not running as the superuser, nor will the servers that are being launched. This is another D-BUS bug. Because of a mis-applied check in the dbus-daemon code, in order to use any helper with a per-user D-BUS broker every D-BUS server definition must have a totally redundant User= setting. The replacement D-BUS files generated by the configuration import subsystem, such as ~username/.local/share/dbus-1/services/org.example.Sheila.service, all have a dummy User= and a dummy Exec= setting, neither of which is actually used. You must do the same in the files that you create yourself.

  6. Create a service bundle in your per-user service bundles area as ~/.config/service-bundles/services/name.