Ahmed S. Darwish wrote on 18/07/15 01:44: > Hi Mantas, > > On Sat, Jul 18, 2015 at 12:17:51AM +0300, Mantas Mikulėnas wrote: >> On Fri, Jul 17, 2015 at 9:38 PM, Ahmed S. Darwish <darwish...@gmail.com> >> wrote: >> >>> Hi everyone, >>> >>> I'm currently transforming a network daemon to become a native >>> ``Type=notify'' systemd service. This daemon uses native PulseAudio >>> simple APIs for output. >>> >>> Due to the PulseAudio dependency, the service needs to run under the >>> user session. Otherwise, all PulseAudio APIs [e.g. pa_simple_new()] >>> returns a ``Connection Refused'' error. [1] >>> >>> Given the above, I've built the following service file: >>> >>> [Unit] >>> Description=AirTunes Synchronous Audio Service >>> [Service] >>> Type=notify >>> ExecStart=/usr/local/bin/shairport-sync >>> [Install] >>> WantedBy=default.target >>> >>> And the following snippet in the package Makefile.am: >>> >>> cp scripts/shairport-sync.service /usr/lib/systemd/user/ >>> systemctl --user daemon-reload >>> systemctl --user enable shairport-sync.service >>> systemctl --user start shairport-sync.service >>> >> >> So the real problem is not that it *doesn't work*, but rather that >> it *shouldn't be done*. That makefile is mixing entirely separate >> things – installation (packaging), global configuration, and >> per-user configuration. >> > > This is a small github project, and you have to handle the > standard `./confugre', `make' and `sudo make install' sequence > out of the box. There's no fancy Debian or Fedora packages for > it even yet. > > The per-use configuration part was forced upon us due to our > dependency on native PulseAudio APIs; APIs which do not work > except when our daemon is run from the same session PulseAudio > is running from. > >> (Not to mention the dangerous assumptions that 1) there's exactly >> one user logged in during installation, and 2) that they'll >> actually want to run the program right now...) >> > > Yes, `systemctl --user' is wrong and specific only to the current > user, but that's why I was asking for an alernative, more generic, > solution that will fit all users in the first place :-) > >>> As you can see, the service is properly installed under >>> ``/usr/lib/systemd/user/'' to run under the systemd user instance. >>> >>> Now the problem is that the Makefile commands above run as root, >>> and thus all the ``systemctl --user'' commands fail with: >>> >>> Failed to get D-Bus connection: Connection refused >>> >>> So, the question is, can I start ``systemctl --user daemon-reload'' >>> and ``systemctl --user enable'' above in some form while the >>> Makefile is run from root? >>> >> >> No, but you don't need to. Just install the file to /usr/lib/systemd/user, >> and that's it. It'll be available to all users. >> >> If you want to forcefully enable the service for all users, then also >> symlink it into /usr/lib/systemd/user/default.target.wants/, which is >> almost exactly what `systemctl enable` does (except system-wide). >> That'll make it start on login for everyone. >> > > Excellent! `systemctl --user enable' always did the symbolic > link under `$HOME/.config/systemd/user/'; I mistakenly thought > that it must be done _only_ this way for each and every user. > > Now I understand; it seems it was done that way just not to affect > other users of the system. It couldn't be done any other way due > to the system permissions of /usr/lib/systemd/user
Note, that this *forces* it on every user, you can also enable it for every user as part of package installation by running "systemctl --global enable <yourservice>" The --global flag means "globally for all users" (it only applies to the user instance, so the --user part is not needed). This writes the enablement symlink into /etc/systemd/user/default.target.wants/ (or whatever your service file states as it's WantedBy= directive). Ultimately this is a packaging issue, so I would suggest that your "make install" does not write anything here, but your document things for packagers that *iff* they want the package to be enabled by all users, then they run "systemctl --global enable <yourservice>" on initial package installation (or better run "systemctl --global preset <yourservice>" to allow package preset system to take on board the distro-wide defaults from *.preset files (see "man 5 systemd.preset") This is ultimately what PulseAudio itself does/recommends when started from the user session as you are trying to do, so I'd suggest you follow suit. >> But the general rule is, do not start user-session processes from system >> tasks. > > Having the service installed `per-user' was something that was > unfortunately forced. I will still inspect what will happen when > two logged-in users lead to two instances of the daemon running :-( Ultimately, if your daemon connects to PA, then you could react appropriately. e.g. if PA is suspended because the user no longer has access to the h/w devices, this information will be made available via PA APIs and your daemon can react accordingly. e.g. if you have two users, and one user wants this service and one does not, then you can react accordingly. e.g. one user may expose their sharing services as "Bob's Laptop" which may be getting used by some systems, but when Alice, logs in (via fast user switch) then it might expose also "Alice's Laptop" and let a different set of devices connect to it. This is kinda how things are meant to work, but it does expose some issues in PA that cross some interesting boundaries. Ultimately people want to use things in different ways... here, you probably don't want to think about "Bob's Laptop" vs. "Alice's Laptop"... I'm guessing you just want to think about "the Laptop that Bob normally uses, but Alice sometimes logs into" and you want to play sound to it be able to play sound on it at all times. This is understandable, but until very recently, the security problems and management rules of device access make this a very hard problem to solve in PA. With the advent of kdbus, some of these security problems can be solved more efficiently now so perhaps one day we'll see a newer version of PA based on kdbus which splits into a system component and a per-user component (various changes are required for proper application sandboxing too) or some other mechanism that would allow you to do this "device level" configuration. I don't honestly know, but there will need to be some serious development done there at some point in the not too distant future. Who will be able to step up and do that work is sadly unknown at this time (to the best of my knowledge anyway). Until then, the best situation is that a given device: 1. will typically belong to one user (I'd say most of the time, there is only one user account anyway) 2. said user would auto-login and thus when the machine is on, the user is logged in an PA is started or 2b. said user has "lingering" enabled (see "man 1 loginctl" and the "enable-linger" verb) and thus starts a per-user dbus/PA/yourservice even when the user has not yet logged in (i.e. waiting on gdm login screen for username+password). This solves the problem for the vast majority of users who want to use your stuff on their own devices. Alice may still sometimes login to Bob's computer and your application should still gracefully handle that (ultimately if PA says it cannot access the audio device, you should propagate that information to any remote clients - this will be as true with any newer structure as it is now, so may as well code defensively for that now!), but for the common case, everything just works. > Can we disable multiple instances of the daemon in a systemd-native > way, even when the service is run per user? No. Ultimately your daemon should just be capable of handling it's access to audio h/w disappearing. Whether this means it just disconnects clients and stops listening on the network, or whether it can pause/cork itself neatly (I guess it depends on the remote protocol) is up to you, but ultimately it should be handled for various reasons, not just this one (e.g. say the user goes on a VoIP call. They likely want to cork/pause any streams playing under those circumstances too - while this isn't exactly the same, it's another situation where PA will tell you to stop playing). > Yes, this question > implies a possible problem in the design, but again, having the > service per-user is the only choice we have so far. > > Thanks a lot Mantas for your help! I hope my reply has shed some light on the situation for you. I'll try and clarify anything that doesn't make sense, if you ask for clarifications. Cheers Col -- Colin Guthrie gmane(at)colin.guthr.ie http://colin.guthr.ie/ Day Job: Tribalogic Limited http://www.tribalogic.net/ Open Source: Mageia Contributor http://www.mageia.org/ PulseAudio Hacker http://www.pulseaudio.org/ Trac Hacker http://trac.edgewall.org/ _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel