Running the application as a daemon does not work, but running it as a regular command does

I have an application that streams audio and video to an external service. The main application is written in Python and does many things like making API calls, turning on/off LEDs, collecting data about the system, waiting for a button to be pressed etc, but the most important part of the application is running a streaming application written in C++ when the button attached to the Raspberry Pi is pressed. It has this snapcraft.yaml:

name: my-app
version: '1.0.0'
summary: summary
description: description
confinement: strict
grade: stable
base: core18

parts:
  alsa-mixin:
    plugin: dump
    source: https://github.com/diddledan/snapcraft-alsa.git
    source-subdir: snapcraft-assets
    build-packages:
      - libasound2-dev
    stage-packages:
      - libasound2
      - libasound2-plugins
      - yad
    stage:
      - etc/asound.conf
      - snap/command-chain/alsa-launch
      - usr/bin/yad*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/libasound*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/libdnsfile*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/libFLAC*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/libjack*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/libpulse*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/libsamplerate*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/libspeex*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/libvorbis*
      - usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio

  libraries:
    plugin: dump
    source: lib/tokbox/lib/.
    organize:
      libopentok.so: lib/libopentok.so
    stage-packages:
      - libc++1
      - libc++abi1

  stream:
    plugin: cmake
    source: .
    build-packages:
      - build-essential
      - libc++-dev
      - libc++abi-dev
      - libuv1-dev
      - libunwind-dev
      - libasound2-dev
      - libsdl2-dev
    stage-packages:
      - libc++1
      - libc++abi1
      - libunwind8
      - libuv1
      - libasound2
      - libasound2-plugins
      - libsdl2-2.0-0
    after:
      - alsa-mixin

  live:
    plugin: python
    source: .

layout:
  /usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib:
    bind: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib
  /usr/share/alsa:
    bind: $SNAP/usr/share/alsa

apps:
  live:
    daemon: simple
    command: bin/live
    command-chain: ["snap/command-chain/alsa-launch"]
    plugs:
      - alsa
      - audio-playback
      - audio-record
      - camera
      - hardware-observe
      - home
      - gpio
      - network
      - network-bind
      - network-control
      - network-observe
      - pulseaudio
      - shutdown
    environment:
      ALSA_CONFIG_PATH: /snap/$SNAPCRAFT_PROJECT_NAME/current/usr/share/alsa/alsa.conf
      ALWAYS_USE_PULSEAUDIO: '1'

And it doesn’t work when I run the “live” application as a daemon. While debugging this problem, I discovered that removing daemon: simple from the configuration fixes this problem. This is not an option for me as I don’t want to run things manually using the snap run command. What can I do to debug this problem? What is the difference between a daemon and a regular command in the SnapCraft package? I don’t have any seccomp or AppArmor violations.

I have collected some logs and I have this:

Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL sysdefault
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL hw:0
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM sysdefault
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL hw:0
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL hw:1
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL hw:2
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL hw:3
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL hw:0
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL sysdefault
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL hw:0
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL sysdefault
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib control.c:1373:(snd_ctl_open_noupdate) Invalid CTL hw:0
Apr 13 18:54:01 raspberrypi my-app.live[142261]: ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM sysdefault

The only difference in the daemon is these lines with “Invalid CTL sysdefault” or “Unknown PCM sysdefault”. Are SnapCraft daemons running with different privileges or configuration than commands?

They’re fully featured Systemd services with root privileges. Due to the AppArmor MAC and other environment quirks, root won’t be able to touch the regular desktop users Pulseaudio daemon/session. Running the command via the shell runs it as your current user with the normal user environment supporting it.

Assuming you have a desktop session running and just want to have the app open automatically on login, you’d want either:

Autostart

User Daemons (Experimental and unlikely to be stable any time soon, it currently needs enabling per snapd installation).

@ogra Does Autostart work in headless mode or do you need to log into the desktop for it to work?

Autostart will put a .desktop file into the xdg desktop session startup, if there is no session things will indeed not start, so yes, you will have to log in.

@James-Carroll @ogra Can you tell me when you plan to release these experimental features into the stable version? I tested user daemon and it solves our problem.

1 Like

FWIW my app (Calaboka) has been using the user daemons experimental feature for almost 2 years with over 800 active users. It fully depends on that feature. I would love to see it become stable and officially supported - it’s a great feature for desktop snaps that need to do background work and interact with other desktop applications, send notifications, etc.

2 Likes

Do we know when the user daemons experimental feature is slated to become stable and officially supported? Is there a chance that this might never happen or be deprecated?

@dloranc and I are working on a project which uses the experimental.user daemon. It seems to work to suit our needs but we ran into an issue where it does not work after rebooting our system. If the daemon is restarted manually, it works again. Is this something you have come up against?

Given the experimental nature of the feature, it may not work well on all systems and linux distributions. I did notice that my user daemon won’t automatically start on some linux installations after logging out of the desktop session and then logging back in. But that’s more the exception than the rule, and it always starts after boot.

My (temporary solution) for this is to have my GUI app detect that the daemon is not running and instruct the user to start the user daemon manually. If your app is just a user daemon, then I’m not sure what to suggest.