From mboxrd@z Thu Jan 1 00:00:00 1970 From: Danny Milosavljevic Subject: Invoking user shepherd; Was: Re: Defining *user* services in Guix Date: Sun, 11 Jun 2017 03:29:00 +0200 Message-ID: <20170611032900.6ac194b9@scratchpost.org> References: <87o9vowfn0.fsf@gmail.com> <20170422203131.610f2a30@scratchpost.org> <878tmsghzk.fsf@gnu.org> <87inlvdr76.fsf@gmail.com> <87r30hbbi7.fsf@gmail.com> <87fugwsx2s.fsf@elephly.net> <8737cu7z0s.fsf@gnu.org> <877f24pnem.fsf@gmail.com> <87mvavk243.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:40484) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dJrgj-0004IJ-Hz for guix-devel@gnu.org; Sat, 10 Jun 2017 21:29:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dJrgg-0006FP-Cx for guix-devel@gnu.org; Sat, 10 Jun 2017 21:29:09 -0400 In-Reply-To: <87mvavk243.fsf@gnu.org> List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: guix-devel@gnu.org Hi, I'm revisiting this topic because I want to have a dbus user bus to be available as "${XDG_RUNTIME_DIR}/bus". > > With the attached patch, it is possibe to use (gnu services herd) to > > interact with a user shepherd instance. Nice! It works! But while testing it I noticed: For a real user shepherd, it would be nice if when I logged in twice using the same user account (without logging out in-between - so resulting in two sessions of that user) it would still only have one shepherd instance for that user account in total - and if that instance (and remaining user processes for that matter) went away only when I logged out from *all* sessions of that user. I thought I could fake that by just trying to invoke shepherd on each session start and have it fail on the second attempt - but apparently we will happily start an infinite number of shepherds for one user. Is that on purpose? The relevant place (in shepherd) is: (define (open-server-socket file-name) "Open a socket at FILE-NAME, and listen for connections there." (with-fluids ((%default-port-encoding "UTF-8")) (let ((sock (socket PF_UNIX SOCK_STREAM 0)) (address (make-socket-address AF_UNIX file-name))) (false-if-exception (delete-file file-name)) ; <===== [dannym: WTF. Would it be better to try to connect first?] (bind sock address) (listen sock 10) sock))) Probably not good. Maybe better: (define (server-present? file-name) "Open a socket at FILE-NAME, and connect to the server, if any. Return #t if that worked." (with-fluids ((%default-port-encoding "UTF-8")) (let ((sock (socket PF_UNIX SOCK_STREAM 0)) (address (make-socket-address AF_UNIX file-name))) (false-if-exception (connect sock address))))) ; probably missing a "[catch] close". How to do that best? (define (open-server-socket file-name) "Open a socket at FILE-NAME, and listen for connections there." (if (server-present? file-name) (exit 0) ; User's shepherd is already running, so let it do its work. (with-fluids ((%default-port-encoding "UTF-8")) (let ((sock (socket PF_UNIX SOCK_STREAM 0)) (address (make-socket-address AF_UNIX file-name))) (false-if-exception (delete-file file-name)) ; we could get rid of that if we put the shepherd socket into /run/user/xxx (i.e. XDG_RUNTIME_DIR) instead, because that's on a tmpfs. That's also where it's supposed to go according to the standard. (bind sock address) (listen sock 10) sock))) elogind already sends a message to the dbus system bus whenever a user really stops or starts (all their sessions closed, one session opened, respectively): p = "/org/freedesktop/login1/user/_"UID_FMT; sd_bus_emit_signal( u->manager->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", new_user ? "UserNew" : "UserRemoved", "uo", (uint32_t) u->uid, p); I'm trying to find the right place to insert my "dbus-daemon" invocation for providing the user bus (note: not session bus)... At first I thought of hard-coding the "dbus-daemon" invocation somewhere but then I thought the option with the most user freedom would be to only invoke the user shepherd [and nothing else] when the user logs in - and if he has a user service launching "dbus-daemon", good for him... Should we make a system shepherd service that invokes the user shepherd service on behalf of users? Would that be that safe? Or should we just expect the user to put a (shepherd with fix) invocation into their HOME startup scripts like .xinitrc ? Note that if we did that there's some session-specific stuff in the session's environment that shepherd will inherit. Probably not that bad if invoked early enough.