]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
Don't go into a respawn loop when the greeter fails
authorunknown <robert.ancell@gmail.com>
Wed, 21 Jul 2010 11:04:01 +0000 (13:04 +0200)
committerunknown <robert.ancell@gmail.com>
Wed, 21 Jul 2010 11:04:01 +0000 (13:04 +0200)
src/display.c
src/session.c
src/session.h

index 736cc0f779b056b7c2f33bd78278cc9dcd536cfa..817bfa7ca9b0be05acd40fa1f0ca536592007e61 100644 (file)
@@ -172,53 +172,77 @@ end_session (Display *display)
 }
 
 static void
-session_exit_cb (Session *session, Display *display)
+handle_end_session (Display *display, Session *session, gboolean clean_exit)
 {
     SessionType active_session;
-
+  
     g_object_unref (display->priv->session);
     display->priv->session = NULL;
 
     active_session = display->priv->active_session;
     display->priv->active_session = SESSION_NONE;
 
-    // FIXME: Check for respawn loops
-    switch (active_session)
+    /* Session ended, return to the greeter */
+    if (active_session == SESSION_USER)
     {
-    case SESSION_NONE:
-        break;
-    case SESSION_GREETER_PRE_CONNECT:
-        g_warning ("Failed to start greeter");
-        break;
-    case SESSION_GREETER:
-        if (display->priv->default_user && display->priv->timeout > 0)
-        {
-            g_debug ("Starting session for default user %s", display->priv->default_user);
-            display->priv->pam_session = pam_session_new (display->priv->default_user);
-            pam_session_authorize (display->priv->pam_session);
-            start_session (display);
-            start_user_session (display);
-        }
-        else
-            start_greeter (display);
-        break;
-    case SESSION_GREETER_AUTHENTICATED:
-        start_user_session (display);
-        break;
-    case SESSION_USER:
+        if (!clean_exit)
+            g_warning ("Session exited unexpectedly");
         end_session (display);
         start_greeter (display);
-        break;
+        return;
     }
+
+    if (!clean_exit)
+    {
+        g_warning ("Greeter failed");
+        return;
+    }
+
+    if (active_session == SESSION_GREETER_PRE_CONNECT)
+    {
+        g_warning ("Greeter quit before connecting");
+        return;
+    }
+
+    /* Greeter successfully chose a user, start their session */
+    if (active_session == SESSION_GREETER_AUTHENTICATED)
+    {
+        start_user_session (display);
+        return;
+    }
+
+    if (display->priv->default_user && display->priv->timeout > 0)
+    {
+        g_debug ("Starting session for default user %s", display->priv->default_user);
+        display->priv->pam_session = pam_session_new (display->priv->default_user);
+        pam_session_authorize (display->priv->pam_session);
+        start_session (display);
+        start_user_session (display);
+    }
+    else
+        start_greeter (display);
+}
+
+static void
+session_exited_cb (Session *session, gint status, Display *display)
+{
+    handle_end_session (display, session, status == 0);
+}
+
+static void
+session_killed_cb (Session *session, gint status, Display *display)
+{
+    handle_end_session (display, session, FALSE);
 }
+
 static void
 open_session (Display *display, const gchar *username, const gchar *command)
 {
     g_return_if_fail (display->priv->session == NULL);
 
     display->priv->session = session_new (username, command);
-    g_signal_connect (G_OBJECT (display->priv->session), "exited", G_CALLBACK (session_exit_cb), display);
+    g_signal_connect (G_OBJECT (display->priv->session), "exited", G_CALLBACK (session_exited_cb), display);
+    g_signal_connect (G_OBJECT (display->priv->session), "killed", G_CALLBACK (session_killed_cb), display);
     session_set_env (display->priv->session, "DISPLAY", xserver_get_address (display->priv->xserver));
     if (display->priv->ck_session)
         session_set_env (display->priv->session, "XDG_SESSION_COOKIE", ck_connector_get_cookie (display->priv->ck_session));
@@ -272,7 +296,7 @@ start_greeter (Display *display)
 {
     GKeyFile *theme;
     GError *error = NULL;
-
+  
     theme = load_theme (display->priv->greeter_theme, &error);
     if (!theme)
         g_warning ("Failed to find theme %s: %s", display->priv->greeter_theme, error->message);
@@ -477,7 +501,7 @@ xserver_ready_cb (XServer *xserver, Display *display)
     /* Don't run any sessions on local terminals */
     if (xserver_get_server_type (xserver) == XSERVER_TYPE_LOCAL_TERMINAL)
         return;
-
+  
     /* If have user then automatically login */
     if (display->priv->default_user && display->priv->timeout == 0)
     {
index b447a1c5df3cb760e897f4a55f0fa8806a490c80..b7fffedf29fb286849761e17373e65caf802db85 100644 (file)
@@ -20,6 +20,7 @@
 
 enum {
     EXITED,
+    KILLED,
     LAST_SIGNAL
 };
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -92,14 +93,18 @@ session_watch_cb (GPid pid, gint status, gpointer data)
 {
     Session *session = data;
 
+    session->priv->pid = 0;
+
     if (WIFEXITED (status))
+    {
         g_debug ("Session exited with return value %d", WEXITSTATUS (status));
+        g_signal_emit (session, signals[EXITED], 0, WEXITSTATUS (status));
+    }
     else if (WIFSIGNALED (status))
+    {
         g_debug ("Session terminated with signal %d", WTERMSIG (status));
-
-    session->priv->pid = 0;
-
-    g_signal_emit (session, signals[EXITED], 0);
+        g_signal_emit (session, signals[KILLED], 0, WTERMSIG (status));
+    }
 }
 
 static void
@@ -156,7 +161,7 @@ session_start (Session *session)
     gchar **argv, **env;
     gchar *env_string;
     GError *error = NULL;
-
+  
     g_return_val_if_fail (session->priv->pid == 0, FALSE);
 
     if (session->priv->username)
@@ -204,7 +209,7 @@ session_start (Session *session)
         return FALSE;
 
     env_string = g_strjoinv (" ", env);
-    g_debug ("Launching greeter: %s %s", env_string, session->priv->command);
+    g_debug ("Launching session: %s %s", env_string, session->priv->command);
     g_free (env_string);
 
     result = g_spawn_async/*_with_pipes*/ (working_dir,
@@ -268,6 +273,14 @@ session_class_init (SessionClass *klass)
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (SessionClass, exited),
                       NULL, NULL,
-                      g_cclosure_marshal_VOID__VOID,
-                      G_TYPE_NONE, 0);
+                      g_cclosure_marshal_VOID__INT,
+                      G_TYPE_NONE, 1, G_TYPE_INT);
+    signals[KILLED] =
+        g_signal_new ("killed",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (SessionClass, killed),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__INT,
+                      G_TYPE_NONE, 1, G_TYPE_INT);
 }
index 1ddb94340fd66c8bd2234d441252cc2bf02e3454..e23905389e5a4ce5c2188ccd7ba079ad4145960c 100644 (file)
@@ -32,7 +32,8 @@ typedef struct
 {
     GObjectClass parent_class;
 
-    void (*exited)(Session *session);
+    void (*exited) (Session *session, int status);
+    void (*killed) (Session *session, int signum);
 } SessionClass;
 
 GType session_get_type (void);