[systemd-commits] src/login

Lennart Poettering lennart at kemper.freedesktop.org
Wed Jan 28 11:04:53 PST 2015


 src/login/logind-seat.c    |   14 +++++++++++++-
 src/login/logind-session.c |   11 +++++++++--
 2 files changed, 22 insertions(+), 3 deletions(-)

New commits:
commit be94d95499bf9c63fe9331e9b9ecc64f32fe9d79
Author: Martin Pitt <martin.pitt at ubuntu.com>
Date:   Wed Jan 28 18:14:01 2015 +0100

    logind: handle closing sessions over daemon restarts
    
    It may happen that you have several sessions with the same VT:
    
     - Open a session c1 which leaves some processes around, and log out. The
       session will stay in State=closing and become Active=no.
     - Log back in on the same VT, get a new session "c2" which is State=active and
       Active=yes.
    
    When restarting logind after that, the first session that matches the current
    VT becomes Active=yes, which will be c1; c2 thus is Active=no and does not get
    the usual polkit/device ACL privileges.
    
    Restore the "closing" state in session_load(), to avoid treating all restored
    sessions as State=active. In seat_active_vt_changed(), prefer active sessions
    over closing ones if more than one session matches the current VT.
    
    Finally, fix the confusing comment in session_load() and explain it a bit
    better.
    
    https://launchpad.net/bugs/1415104

diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 197138c..126c5b8 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -340,12 +340,24 @@ int seat_active_vt_changed(Seat *s, unsigned int vtnr) {
 
         log_debug("VT changed to %u", vtnr);
 
+        /* we might have earlier closing sessions on the same VT, so try to
+         * find a running one first */
         LIST_FOREACH(sessions_by_seat, i, s->sessions)
-                if (i->vtnr == vtnr) {
+                if (i->vtnr == vtnr && !i->stopping) {
                         new_active = i;
                         break;
                 }
 
+        if (!new_active) {
+                /* no running one? then we can't decide which one is the
+                 * active one, let the first one win */
+                LIST_FOREACH(sessions_by_seat, i, s->sessions)
+                        if (i->vtnr == vtnr) {
+                                new_active = i;
+                                break;
+                        }
+        }
+
         r = seat_set_active(s, new_active);
         manager_spawn_autovt(s->manager, vtnr);
 
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index a51f9f3..a02a537 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -301,6 +301,7 @@ int session_load(Session *s) {
         _cleanup_free_ char *remote = NULL,
                 *seat = NULL,
                 *vtnr = NULL,
+                *state = NULL,
                 *pos = NULL,
                 *leader = NULL,
                 *type = NULL,
@@ -327,6 +328,7 @@ int session_load(Session *s) {
                            "SERVICE",        &s->service,
                            "DESKTOP",        &s->desktop,
                            "VTNR",           &vtnr,
+                           "STATE",          &state,
                            "POS",            &pos,
                            "LEADER",         &leader,
                            "TYPE",           &type,
@@ -415,13 +417,18 @@ int session_load(Session *s) {
                         s->class = c;
         }
 
+        if (state && streq(state, "closing"))
+                s->stopping = true;
+
         if (s->fifo_path) {
                 int fd;
 
                 /* If we open an unopened pipe for reading we will not
                    get an EOF. to trigger an EOF we hence open it for
-                   reading, but close it right-away which then will
-                   trigger the EOF. */
+                   writing, but close it right away which then will
+                   trigger the EOF. This will happen immediately if no
+                   other process has the FIFO open for writing, i. e.
+                   when the session died before logind (re)started. */
 
                 fd = session_create_fifo(s);
                 safe_close(fd);



More information about the systemd-commits mailing list