[systemd-devel] Session-specific user services
Simon McVittie
smcv at collabora.com
Tue Apr 6 11:51:56 UTC 2021
On Fri, 02 Apr 2021 at 20:54:05 +0300, Arseny Maslennikov wrote:
> There's at least a use case to know if an active session owned by the
> UID is present on seat X:
> https://gitlab.gnome.org/GNOME/gvfs/-/issues/557
> In short, if a USB storage drive is connected to a particular seat,
> we'd like to only try automounting it on that seat, and not on a random
> seat that wins a race condition.
Consider this system:
uid 1000
\- login session 1 on seat 1
\- GNOME
\- login session 2 on seat 2
\- getty/bash
\- systemd --user
\- gvfsd process 11111
uid 2000
\- login session 3 on seat 3
\- GNOME
\- login session 4 on seat 4
\- getty/bash
\- systemd --user
\- gvfsd process 22222
(Note that this is already a bit silly because each of uid 1000 and uid
2000 presumably represents a person, and at any given time, that person
is physically sitting in at most one seat...)
If gvfsd is a `systemd --user` service, then there are two instances of it:
one for uid 1000, and one for uid 2000. It is *not* the case that there are
four instances of it, one per seat.
Now we plug a USB drive into seat 3, and another USB drive into seat 4.
Suppose both users have configured gvfsd to automount USB drives. What
we want is that uid 1000 does not mount either of the USB drives (even
if they have the necessary permissions), and uid 2000 mounts both of them.
You seem to be suggesting that the right logic is for each gvfsd instance
to run this pseudocode:
# Here get_login_session() is assumed to return non-null even if the
# process is a systemd --user service. Will it return 3 or 4 for
# uid 2000's gvfsd? It can only return one of those!
if this_process.get_login_session().seat == usb_drive.seat:
usb_drive.do_automount()
I don't think that's right, though: assuming get_login_session() is
deterministic, we will only automount *either* the USB drive on seat 3
*or* the one on seat 4, not both.
I think the logic we want in gvfsd is probably more like this:
for login_session in this_uid.get_login_sessions():
if login_session.seat == usb_drive.seat:
usb_drive.do_automount()
break
Or, perhaps even better:
# This time we want this to return null if this process is a
# systemd --user service
login_session = this_process.get_login_session()
if login_session:
# traditional D-Bus activation, or XDG autostart, or run in the
# foreground for development/debugging; responsible for only its
# own login session
if login_session.seat == usb_drive.seat:
usb_drive.do_automount()
else:
# systemd --user service, shared by all our login sessions
for login_session in this_uid.get_login_sessions():
if login_session.seat == usb_drive.seat:
usb_drive.do_automount()
break
either of which will do the right thing: uid 1000 will not automount either
of the USB sticks (even if they have permissions to do so), and uid 2000
will automount both of them.
smcv
More information about the systemd-devel
mailing list