Providing a dbus slot: “dbus-launch” executable file not found in $PATH

Hello and thanks for your attention. Currently we are testing snapcraft usage as we plan to develop for IoT devices with Ubuntu Core, but we are running into a problem when trying to provide an interface slot using dbus. With this snapcraft.yaml, we can package the snap and install it, but it fails on launch when trying to bind to the dbus with the following message: “dbus-launch” executable file not found in $PATH

This is our first snapcraft.yaml. The app we are looking to bind to dbus is mycompanydbus:

name: gohelloworldmycompany
version: git
summary: Hello World
description: Hello World!
confinement: strict
grade: devel

parts:
  gohelloworldmycompany:
    plugin: go
    source-type: local
    source: .
    go-importpath: mycompany.es/myproject/snaps

apps:
  gohelloworldmycompany:
    daemon: simple
    command: gohelloworldmycompany
  ghwmserver:
    daemon: simple
    command: goserver
  mycompanybus:
    daemon: simple
    command: mycompanydbus
    slots:
      - dbus-mycompanydbus

plugs:
  network:
  network-bind:
slots:
  dbus-mycompanydbus:
    interface: dbus
    bus: session
    name: es.mycompany.mycompanydbus

After getting that error, we looked around and found that we might have to add dbus-x11 to sage-packages, so we did that. Then with the following snapcraft.yaml configuration, we weren’t able to package the app:

name: gohelloworldmycompany
version: git
summary: Hello World
description: Hello World!
confinement: strict
grade: devel

parts:
  gohelloworldmycompany:
    plugin: go
    source-type: local
    source: .
    go-importpath: mycompany.es/myproject/snaps
    stage-packages:
      - dbus-x11

apps:
  gohelloworldmaycompany:
    daemon: simple
    command: gohelloworldmycompany
  ghwmserver:
    daemon: simple
    command: goserver
  mycompanybus:
    daemon: simple
    command: mycompanydbus
    slots:
      - dbus-mycompanydbus

plugs:
  network:
  network-bind:
slots:
  dbus-mycompanydbus:
    interface: dbus
    bus: session
    name: es.mycompany.mycompanydbus

The error that we got while packaging the snap with the command “snapcraft --target-arch=armhf” is:

Priming gohelloworldmycompany
Unable to determine library dependencies for '/builds/CDR/174-3-project-snaps/prime/bin/goserver'
Unable to determine library dependencies for '/builds/CDR/174-3-project-snaps/prime/bin/mycompanydbus'
Unable to determine library dependencies for '/builds/CDR/174-3-project-snaps/prime/bin/gohelloworldmycompany'
Files from the build host were migrated into the snap to satisfy dependencies that would otherwise not be met. This feature will be removed in a future release. If these libraries are needed in the final snap, ensure that the following are either satisfied by a stage-packages entry or through a part:
lib/x86_64-linux-gnu/libaudit.so.1
lib/x86_64-linux-gnu/libgcrypt.so.20
lib/x86_64-linux-gnu/libgpg-error.so.0
lib/x86_64-linux-gnu/liblzma.so.5
lib/x86_64-linux-gnu/libpcre.so.3
lib/x86_64-linux-gnu/libselinux.so.1
lib/x86_64-linux-gnu/libsystemd.so.0
usr/lib/x86_64-linux-gnu/liblz4.so.1
The linker version '2.23' used by the base 'core' is incompatible with files in this snap:
    /builds/CDR/174-3-project-snaps/prime/lib/x86_64-linux-gnu/libbsd.so.0.8.7 (2.25)
    /builds/CDR/174-3-project-snaps/prime/lib/x86_64-linux-gnu/libexpat.so.1.6.7 (2.25)
    /builds/CDR/174-3-project-snaps/prime/usr/lib/x86_64-linux-gnu/libexpatw.so.1.6.7 (2.25)

Just in case, this is the code we are using to bind to dbus:
main.go:

package main

import (
	"fmt"
	"github.com/godbus/dbus"
)

func main() {
	conn, err := dbus.SessionBus()
	if err != nil {
		panic(err)
	}

	reply, err := conn.RequestName("es.mycompany.mycompanydbus", dbus.NameFlagDoNotQueue)
	if reply != dbus.RequestNameReplyPrimaryOwner {
		panic("The name es.mycompany.mycompanydbus is already in use")
	}

	err = conn.Export(testFunc, "/es/mycompany/mycompanydbus", "es.mycompany.mycompanydbus")
	if err != nil {
		panic(err)
	}

	c := make(chan *dbus.Signal)
	conn.Signal(c)
	fmt.Println("Mycompanydbus initialized")
	for _ = range c {
	}
}

func testFunc(input string) (res string, err error) {
	return "testFunc called with input " + input, nil
}

The main problem here is that you’re trying to make a system wide daemon (i.e. one instance per machine) talk to the D-Bus session bus (i.e. one instance per user). The error comes from your app trying to launch a new session bus for the root user, which is probably not what you’d want anyway since the user would not be able to access that session bus.

If you really want a system level service, then you should use the D-Bus system bus. User level processes will be able to contact the system bus, so everything should work out.

If you want your daemon to run as a the user (which would mean one instance per user on multiuser systems), snapd doesn’t have a good solution for this yet. It should come in the future, but there is some infrastructure work needed to make sure upgrades of snaps using user daemons are robust.

1 Like

Thank you jamesh, using the system bus solved my problem. I didn’t think about that, and using the system bus makes total sense for my use case so everything’s fine.

It’d probably make sense to issue a warning or error when trying to add a dbus session plug or slot to a system daemon app. I don’t think there is a valid use for the way you’d set up your snapcraft.yaml, so a reasonable error would have made the mistake evident. I guess that’s something we can improve on.

1 Like