[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Invoking user shepherd; Was: Re: Defining *user* services in Guix
From: |
Danny Milosavljevic |
Subject: |
Invoking user shepherd; Was: Re: Defining *user* services in Guix |
Date: |
Sun, 11 Jun 2017 03:29:00 +0200 |
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.
- Invoking user shepherd; Was: Re: Defining *user* services in Guix,
Danny Milosavljevic <=