Blame SOURCES/0002-session-worker-kill-user-sessions-when-stopping-gdm-.patch

675525
From 35a4d47385d043cf4df62c2723508e4edce4dfb4 Mon Sep 17 00:00:00 2001
675525
From: Xiaoguang Wang <xwang@suse.com>
675525
Date: Thu, 16 May 2019 13:26:16 +0800
675525
Subject: [PATCH 2/7] session-worker: kill user sessions when stopping gdm
675525
 service
675525
675525
At the moment the session worker exits as soon as it gets SIGTERM.
675525
That means it may fail to stop the user session (which only happens
675525
in the orderly shutdown path).
675525
675525
This commit sets up a SIGTERM handler that integrates with and
675525
quits the main loop after the session is started.
675525
675525
It still retains the _exit-on-SIGTERM behavior before the session
675525
is started, to ensure a stuck pam module doesn't prevent the
675525
process from dying.
675525
675525
Some small changes to commit by Ray Strode.
675525
675525
Closes #400
675525
---
675525
 daemon/gdm-session-worker.c  | 38 +++++++++++++++++++++++++++---------
675525
 daemon/session-worker-main.c | 33 +++++++++++++++++++++++++++++++
675525
 2 files changed, 62 insertions(+), 9 deletions(-)
675525
675525
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
675525
index d897779f3..e526fa5db 100644
675525
--- a/daemon/gdm-session-worker.c
675525
+++ b/daemon/gdm-session-worker.c
675525
@@ -159,60 +159,61 @@ struct GdmSessionWorkerPrivate
675525
         guint32           display_is_initial : 1;
675525
         guint             state_change_idle_id;
675525
         GdmSessionDisplayMode display_mode;
675525
 
675525
         char                 *server_address;
675525
         GDBusConnection      *connection;
675525
         GdmDBusWorkerManager *manager;
675525
 
675525
         GHashTable         *reauthentication_requests;
675525
 
675525
         GdmSessionAuditor  *auditor;
675525
         GdmSessionSettings *user_settings;
675525
 
675525
         GDBusMethodInvocation *pending_invocation;
675525
 };
675525
 
675525
 #ifdef SUPPORTS_PAM_EXTENSIONS
675525
 static char gdm_pam_extension_environment_block[_POSIX_ARG_MAX];
675525
 
675525
 static const char * const
675525
 gdm_supported_pam_extensions[] = {
675525
         GDM_PAM_EXTENSION_CHOICE_LIST,
675525
         NULL
675525
 };
675525
 #endif
675525
 
675525
 enum {
675525
         PROP_0,
675525
         PROP_SERVER_ADDRESS,
675525
         PROP_IS_REAUTH_SESSION,
675525
+        PROP_STATE,
675525
 };
675525
 
675525
 static void     gdm_session_worker_class_init   (GdmSessionWorkerClass *klass);
675525
 static void     gdm_session_worker_init         (GdmSessionWorker      *session_worker);
675525
 static void     gdm_session_worker_finalize     (GObject               *object);
675525
 
675525
 static void     gdm_session_worker_set_environment_variable (GdmSessionWorker *worker,
675525
                                                              const char       *key,
675525
                                                              const char       *value);
675525
 
675525
 static void     queue_state_change              (GdmSessionWorker      *worker);
675525
 
675525
 static void     worker_interface_init           (GdmDBusWorkerIface *iface);
675525
 
675525
 
675525
 typedef int (* GdmSessionWorkerPamNewMessagesFunc) (int,
675525
                                                     const struct pam_message **,
675525
                                                     struct pam_response **,
675525
                                                     gpointer);
675525
 
675525
 G_DEFINE_TYPE_WITH_CODE (GdmSessionWorker,
675525
                          gdm_session_worker,
675525
                          GDM_DBUS_TYPE_WORKER_SKELETON,
675525
                          G_IMPLEMENT_INTERFACE (GDM_DBUS_TYPE_WORKER,
675525
                                                 worker_interface_init))
675525
 
675525
 /* adapted from glib script_execute */
675525
 static void
675525
 script_execute (const gchar *file,
675525
                 char       **argv,
675525
@@ -966,100 +967,111 @@ jump_to_vt (GdmSessionWorker  *worker,
675525
 
675525
                 g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker");
675525
                 if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) {
675525
                         g_debug ("GdmSessionWorker: couldn't set graphics mode: %m");
675525
                 }
675525
 
675525
                 /* It's possible that the current VT was left in a broken
675525
                  * combination of states (KD_GRAPHICS with VT_AUTO), that
675525
                  * can't be switched away from.  This call makes sure things
675525
                  * are set in a way that VT_ACTIVATE should work and
675525
                  * VT_WAITACTIVE shouldn't hang.
675525
                  */
675525
                 fix_terminal_vt_mode (worker, active_vt_tty_fd);
675525
         } else {
675525
                 fd = active_vt_tty_fd;
675525
         }
675525
 
675525
         handle_terminal_vt_switches (worker, fd);
675525
 
675525
         if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
675525
                 g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
675525
                          vt_number);
675525
         } else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) {
675525
                 g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m",
675525
                          vt_number);
675525
         }
675525
 
675525
         close (active_vt_tty_fd);
675525
 }
675525
 
675525
+static void
675525
+gdm_session_worker_set_state (GdmSessionWorker      *worker,
675525
+                              GdmSessionWorkerState  state)
675525
+{
675525
+        if (worker->priv->state == state)
675525
+                return;
675525
+
675525
+        worker->priv->state = state;
675525
+        g_object_notify (G_OBJECT (worker), "state");
675525
+}
675525
+
675525
 static void
675525
 gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
675525
                                      int               status)
675525
 {
675525
         g_debug ("GdmSessionWorker: uninitializing PAM");
675525
 
675525
         if (worker->priv->pam_handle == NULL)
675525
                 return;
675525
 
675525
         gdm_session_worker_get_username (worker, NULL);
675525
 
675525
         if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
675525
                 pam_close_session (worker->priv->pam_handle, 0);
675525
                 gdm_session_auditor_report_logout (worker->priv->auditor);
675525
         } else {
675525
                 gdm_session_auditor_report_login_failure (worker->priv->auditor,
675525
                                                           status,
675525
                                                           pam_strerror (worker->priv->pam_handle, status));
675525
         }
675525
 
675525
         if (worker->priv->state >= GDM_SESSION_WORKER_STATE_ACCREDITED) {
675525
                 pam_setcred (worker->priv->pam_handle, PAM_DELETE_CRED);
675525
         }
675525
 
675525
         pam_end (worker->priv->pam_handle, status);
675525
         worker->priv->pam_handle = NULL;
675525
 
675525
         gdm_session_worker_stop_auditor (worker);
675525
 
675525
         if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) {
675525
                 if (worker->priv->login_vt != worker->priv->session_vt) {
675525
                         jump_to_vt (worker, worker->priv->login_vt);
675525
                 }
675525
         }
675525
 
675525
         worker->priv->login_vt = 0;
675525
         worker->priv->session_vt = 0;
675525
 
675525
         g_debug ("GdmSessionWorker: state NONE");
675525
-        worker->priv->state = GDM_SESSION_WORKER_STATE_NONE;
675525
+        gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_NONE);
675525
 }
675525
 
675525
 static char *
675525
 _get_tty_for_pam (const char *x11_display_name,
675525
                   const char *display_device)
675525
 {
675525
 #ifdef __sun
675525
         return g_strdup (display_device);
675525
 #else
675525
         return g_strdup (x11_display_name);
675525
 #endif
675525
 }
675525
 
675525
 #ifdef PAM_XAUTHDATA
675525
 static struct pam_xauth_data *
675525
 _get_xauth_for_pam (const char *x11_authority_file)
675525
 {
675525
         FILE                  *fh;
675525
         Xauth                 *auth = NULL;
675525
         struct pam_xauth_data *retval = NULL;
675525
         gsize                  len = sizeof (*retval) + 1;
675525
 
675525
         fh = fopen (x11_authority_file, "r");
675525
         if (fh) {
675525
                 auth = XauReadAuth (fh);
675525
                 fclose (fh);
675525
         }
675525
         if (auth) {
675525
                 len += auth->name_length + auth->data_length;
675525
                 retval = g_malloc0 (len);
675525
@@ -1168,61 +1180,61 @@ gdm_session_worker_initialize_pam (GdmSessionWorker   *worker,
675525
                         goto out;
675525
                 }
675525
         }
675525
 
675525
         /* set RHOST */
675525
         if (hostname != NULL && hostname[0] != '\0') {
675525
                 error_code = pam_set_item (worker->priv->pam_handle, PAM_RHOST, hostname);
675525
                 g_debug ("error informing authentication system of user's hostname %s: %s",
675525
                          hostname,
675525
                          pam_strerror (worker->priv->pam_handle, error_code));
675525
 
675525
                 if (error_code != PAM_SUCCESS) {
675525
                         g_set_error (error,
675525
                                      GDM_SESSION_WORKER_ERROR,
675525
                                      GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
675525
                                      "%s", "");
675525
                         goto out;
675525
                 }
675525
         }
675525
 
675525
         /* set seat ID */
675525
         if (seat_id != NULL && seat_id[0] != '\0') {
675525
                 gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id);
675525
         }
675525
 
675525
         if (strcmp (service, "gdm-launch-environment") == 0) {
675525
                 gdm_session_worker_set_environment_variable (worker, "XDG_SESSION_CLASS", "greeter");
675525
         }
675525
 
675525
         g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
675525
-        worker->priv->state = GDM_SESSION_WORKER_STATE_SETUP_COMPLETE;
675525
+        gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE);
675525
 
675525
         /* Temporarily set PAM_TTY with the currently active VT (login screen) 
675525
            PAM_TTY will be reset with the users VT right before the user session is opened */
675525
         ensure_login_vt (worker);
675525
         g_snprintf (tty_string, 256, "/dev/tty%d", worker->priv->login_vt);
675525
         pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
675525
         if (!display_is_local)
675525
                 worker->priv->password_is_required = TRUE;
675525
 
675525
  out:
675525
         if (error_code != PAM_SUCCESS) {
675525
                 gdm_session_worker_uninitialize_pam (worker, error_code);
675525
                 return FALSE;
675525
         }
675525
 
675525
         return TRUE;
675525
 }
675525
 
675525
 static gboolean
675525
 gdm_session_worker_authenticate_user (GdmSessionWorker *worker,
675525
                                       gboolean          password_is_required,
675525
                                       GError          **error)
675525
 {
675525
         int error_code;
675525
         int authentication_flags;
675525
 
675525
         g_debug ("GdmSessionWorker: authenticating user %s", worker->priv->username);
675525
 
675525
         authentication_flags = 0;
675525
 
675525
@@ -1233,61 +1245,61 @@ gdm_session_worker_authenticate_user (GdmSessionWorker *worker,
675525
         /* blocking call, does the actual conversation */
675525
         error_code = pam_authenticate (worker->priv->pam_handle, authentication_flags);
675525
 
675525
         if (error_code == PAM_AUTHINFO_UNAVAIL) {
675525
                 g_debug ("GdmSessionWorker: authentication service unavailable");
675525
 
675525
                 g_set_error (error,
675525
                              GDM_SESSION_WORKER_ERROR,
675525
                              GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE,
675525
                              "%s", "");
675525
                 goto out;
675525
         } else if (error_code != PAM_SUCCESS) {
675525
                 g_debug ("GdmSessionWorker: authentication returned %d: %s", error_code, pam_strerror (worker->priv->pam_handle, error_code));
675525
 
675525
                 /*
675525
                  * Do not display a different message for user unknown versus
675525
                  * a failed password for a valid user.
675525
                  */
675525
                 if (error_code == PAM_USER_UNKNOWN) {
675525
                         error_code = PAM_AUTH_ERR;
675525
                 }
675525
 
675525
                 g_set_error (error,
675525
                              GDM_SESSION_WORKER_ERROR,
675525
                              GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
675525
                              "%s", get_friendly_error_message (error_code));
675525
                 goto out;
675525
         }
675525
 
675525
         g_debug ("GdmSessionWorker: state AUTHENTICATED");
675525
-        worker->priv->state = GDM_SESSION_WORKER_STATE_AUTHENTICATED;
675525
+        gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_AUTHENTICATED);
675525
 
675525
  out:
675525
         if (error_code != PAM_SUCCESS) {
675525
                 gdm_session_worker_uninitialize_pam (worker, error_code);
675525
                 return FALSE;
675525
         }
675525
 
675525
         return TRUE;
675525
 }
675525
 
675525
 static gboolean
675525
 gdm_session_worker_authorize_user (GdmSessionWorker *worker,
675525
                                    gboolean          password_is_required,
675525
                                    GError          **error)
675525
 {
675525
         int error_code;
675525
         int authentication_flags;
675525
 
675525
         g_debug ("GdmSessionWorker: determining if authenticated user (password required:%d) is authorized to session",
675525
                  password_is_required);
675525
 
675525
         authentication_flags = 0;
675525
 
675525
         if (password_is_required) {
675525
                 authentication_flags |= PAM_DISALLOW_NULL_AUTHTOK;
675525
         }
675525
 
675525
         /* check that the account isn't disabled or expired
675525
          */
675525
         error_code = pam_acct_mgmt (worker->priv->pam_handle, authentication_flags);
675525
@@ -1298,61 +1310,61 @@ gdm_session_worker_authorize_user (GdmSessionWorker *worker,
675525
                 g_debug ("GdmSessionWorker: authenticated user requires new auth token");
675525
                 error_code = pam_chauthtok (worker->priv->pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
675525
 
675525
                 gdm_session_worker_get_username (worker, NULL);
675525
 
675525
                 if (error_code != PAM_SUCCESS) {
675525
                         gdm_session_auditor_report_password_change_failure (worker->priv->auditor);
675525
                 } else {
675525
                         gdm_session_auditor_report_password_changed (worker->priv->auditor);
675525
                 }
675525
         }
675525
 
675525
         /* If the user is reauthenticating, then authorization isn't required to
675525
          * proceed, the user is already logged in after all.
675525
          */
675525
         if (worker->priv->is_reauth_session) {
675525
                 error_code = PAM_SUCCESS;
675525
         }
675525
 
675525
         if (error_code != PAM_SUCCESS) {
675525
                 g_debug ("GdmSessionWorker: user is not authorized to log in: %s",
675525
                          pam_strerror (worker->priv->pam_handle, error_code));
675525
                 g_set_error (error,
675525
                              GDM_SESSION_WORKER_ERROR,
675525
                              GDM_SESSION_WORKER_ERROR_AUTHORIZING,
675525
                              "%s", get_friendly_error_message (error_code));
675525
                 goto out;
675525
         }
675525
 
675525
         g_debug ("GdmSessionWorker: state AUTHORIZED");
675525
-        worker->priv->state = GDM_SESSION_WORKER_STATE_AUTHORIZED;
675525
+        gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_AUTHORIZED);
675525
 
675525
  out:
675525
         if (error_code != PAM_SUCCESS) {
675525
                 gdm_session_worker_uninitialize_pam (worker, error_code);
675525
                 return FALSE;
675525
         }
675525
 
675525
         return TRUE;
675525
 }
675525
 
675525
 static void
675525
 gdm_session_worker_set_environment_variable (GdmSessionWorker *worker,
675525
                                              const char       *key,
675525
                                              const char       *value)
675525
 {
675525
         int error_code;
675525
         char *environment_entry;
675525
 
675525
         if (value != NULL) {
675525
                 environment_entry = g_strdup_printf ("%s=%s", key, value);
675525
         } else {
675525
                 /* empty value means "remove from environment" */
675525
                 environment_entry = g_strdup (key);
675525
         }
675525
 
675525
         error_code = pam_putenv (worker->priv->pam_handle,
675525
                                  environment_entry);
675525
 
675525
         if (error_code != PAM_SUCCESS) {
675525
                 g_warning ("cannot put %s in pam environment: %s\n",
675525
@@ -1710,61 +1722,61 @@ gdm_session_worker_accredit_user (GdmSessionWorker  *worker,
675525
 
675525
         /* If the user is reauthenticating and they've made it this far, then there
675525
          * is no reason we should lock them out of their session.  They've already
675525
          * proved they are they same person who logged in, and that's all we care
675525
          * about.
675525
          */
675525
         if (worker->priv->is_reauth_session) {
675525
                 error_code = PAM_SUCCESS;
675525
         }
675525
 
675525
         if (error_code != PAM_SUCCESS) {
675525
                 g_set_error (error,
675525
                              GDM_SESSION_WORKER_ERROR,
675525
                              GDM_SESSION_WORKER_ERROR_GIVING_CREDENTIALS,
675525
                              "%s",
675525
                              pam_strerror (worker->priv->pam_handle, error_code));
675525
                 goto out;
675525
         }
675525
 
675525
         ret = TRUE;
675525
 
675525
  out:
675525
         g_free (home);
675525
         g_free (shell);
675525
         if (ret) {
675525
                 g_debug ("GdmSessionWorker: state ACCREDITED");
675525
                 ret = TRUE;
675525
 
675525
                 gdm_session_worker_get_username (worker, NULL);
675525
                 gdm_session_auditor_report_user_accredited (worker->priv->auditor);
675525
-                worker->priv->state = GDM_SESSION_WORKER_STATE_ACCREDITED;
675525
+                gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCREDITED);
675525
         } else {
675525
                 gdm_session_worker_uninitialize_pam (worker, error_code);
675525
         }
675525
 
675525
         return ret;
675525
 }
675525
 
675525
 static const char * const *
675525
 gdm_session_worker_get_environment (GdmSessionWorker *worker)
675525
 {
675525
         return (const char * const *) pam_getenvlist (worker->priv->pam_handle);
675525
 }
675525
 
675525
 static gboolean
675525
 run_script (GdmSessionWorker *worker,
675525
             const char       *dir)
675525
 {
675525
         /* scripts are for non-program sessions only */
675525
         if (worker->priv->is_program_session) {
675525
                 return TRUE;
675525
         }
675525
 
675525
         return gdm_run_script (dir,
675525
                                worker->priv->username,
675525
                                worker->priv->x11_display_name,
675525
                                worker->priv->display_is_local? NULL : worker->priv->hostname,
675525
                                worker->priv->x11_authority_file);
675525
 }
675525
 
675525
 static void
675525
@@ -2154,61 +2166,61 @@ gdm_session_worker_start_session (GdmSessionWorker  *worker,
675525
                                      (char **)
675525
                                      environment,
675525
                                      TRUE);
675525
 
675525
                 gdm_log_init ();
675525
                 g_debug ("GdmSessionWorker: child '%s' could not be started: %s",
675525
                          worker->priv->arguments[0],
675525
                          g_strerror (errno));
675525
 
675525
                 _exit (EXIT_FAILURE);
675525
         }
675525
 
675525
         if (worker->priv->session_tty_fd > 0) {
675525
                 close (worker->priv->session_tty_fd);
675525
                 worker->priv->session_tty_fd = -1;
675525
         }
675525
 
675525
         /* If we end up execing again, make sure we don't use the executable context set up
675525
          * by pam_selinux durin pam_open_session
675525
          */
675525
 #ifdef HAVE_SELINUX
675525
         setexeccon (NULL);
675525
 #endif
675525
 
675525
         worker->priv->child_pid = session_pid;
675525
 
675525
         g_debug ("GdmSessionWorker: session opened creating reply...");
675525
         g_assert (sizeof (GPid) <= sizeof (int));
675525
 
675525
         g_debug ("GdmSessionWorker: state SESSION_STARTED");
675525
-        worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_STARTED;
675525
+        gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_STARTED);
675525
 
675525
         gdm_session_worker_watch_child (worker);
675525
 
675525
  out:
675525
         if (error_code != PAM_SUCCESS) {
675525
                 gdm_session_worker_uninitialize_pam (worker, error_code);
675525
                 return FALSE;
675525
         }
675525
 
675525
         return TRUE;
675525
 }
675525
 
675525
 static gboolean
675525
 set_up_for_new_vt (GdmSessionWorker *worker)
675525
 {
675525
         int fd;
675525
         char vt_string[256], tty_string[256];
675525
         int session_vt = 0;
675525
 
675525
         fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
675525
 
675525
         if (fd < 0) {
675525
                 g_debug ("GdmSessionWorker: couldn't open VT master: %m");
675525
                 return FALSE;
675525
         }
675525
 
675525
         if (worker->priv->display_is_initial) {
675525
                 session_vt = atoi (GDM_INITIAL_VT);
675525
         } else {
675525
                 if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
675525
@@ -2377,61 +2389,61 @@ gdm_session_worker_open_session (GdmSessionWorker  *worker,
675525
                 break;
675525
         case GDM_SESSION_DISPLAY_MODE_NEW_VT:
675525
         case GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED:
675525
                 if (!set_up_for_new_vt (worker)) {
675525
                         g_set_error (error,
675525
                                      GDM_SESSION_WORKER_ERROR,
675525
                                      GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
675525
                                      "Unable to open VT");
675525
                         return FALSE;
675525
                 }
675525
                 break;
675525
         }
675525
 
675525
         flags = 0;
675525
 
675525
         if (worker->priv->is_program_session) {
675525
                 flags |= PAM_SILENT;
675525
         }
675525
 
675525
         error_code = pam_open_session (worker->priv->pam_handle, flags);
675525
 
675525
         if (error_code != PAM_SUCCESS) {
675525
                 g_set_error (error,
675525
                              GDM_SESSION_WORKER_ERROR,
675525
                              GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
675525
                              "%s", pam_strerror (worker->priv->pam_handle, error_code));
675525
                 goto out;
675525
         }
675525
 
675525
         g_debug ("GdmSessionWorker: state SESSION_OPENED");
675525
-        worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_OPENED;
675525
+        gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_OPENED);
675525
 
675525
         session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID");
675525
 
675525
         if (session_id != NULL) {
675525
                 g_free (worker->priv->session_id);
675525
                 worker->priv->session_id = session_id;
675525
         }
675525
 
675525
  out:
675525
         if (error_code != PAM_SUCCESS) {
675525
                 gdm_session_worker_uninitialize_pam (worker, error_code);
675525
                 return FALSE;
675525
         }
675525
 
675525
         gdm_session_worker_get_username (worker, NULL);
675525
         gdm_session_auditor_report_login (worker->priv->auditor);
675525
 
675525
         return TRUE;
675525
 }
675525
 
675525
 static void
675525
 gdm_session_worker_set_server_address (GdmSessionWorker *worker,
675525
                                        const char       *address)
675525
 {
675525
         g_free (worker->priv->server_address);
675525
         worker->priv->server_address = g_strdup (address);
675525
 }
675525
 
675525
 static void
675525
 gdm_session_worker_set_is_reauth_session (GdmSessionWorker *worker,
675525
@@ -2454,61 +2466,61 @@ gdm_session_worker_set_property (GObject      *object,
675525
         case PROP_SERVER_ADDRESS:
675525
                 gdm_session_worker_set_server_address (self, g_value_get_string (value));
675525
                 break;
675525
         case PROP_IS_REAUTH_SESSION:
675525
                 gdm_session_worker_set_is_reauth_session (self, g_value_get_boolean (value));
675525
                 break;
675525
         default:
675525
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
675525
                 break;
675525
         }
675525
 }
675525
 
675525
 static void
675525
 gdm_session_worker_get_property (GObject    *object,
675525
                                 guint       prop_id,
675525
                                 GValue     *value,
675525
                                 GParamSpec *pspec)
675525
 {
675525
         GdmSessionWorker *self;
675525
 
675525
         self = GDM_SESSION_WORKER (object);
675525
 
675525
         switch (prop_id) {
675525
         case PROP_SERVER_ADDRESS:
675525
                 g_value_set_string (value, self->priv->server_address);
675525
                 break;
675525
         case PROP_IS_REAUTH_SESSION:
675525
                 g_value_set_boolean (value, self->priv->is_reauth_session);
675525
                 break;
675525
         case PROP_STATE:
675525
-                g_value_set_int (value, self->priv->state);
675525
+                g_value_set_enum (value, self->priv->state);
675525
                 break;
675525
         default:
675525
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
675525
                 break;
675525
         }
675525
 }
675525
 
675525
 static gboolean
675525
 gdm_session_worker_handle_set_environment_variable (GdmDBusWorker         *object,
675525
                                                     GDBusMethodInvocation *invocation,
675525
                                                     const char            *key,
675525
                                                     const char            *value)
675525
 {
675525
         GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
675525
         gdm_session_worker_set_environment_variable (worker, key, value);
675525
         gdm_dbus_worker_complete_set_environment_variable (object, invocation);
675525
         return TRUE;
675525
 }
675525
 
675525
 static gboolean
675525
 gdm_session_worker_handle_set_session_name (GdmDBusWorker         *object,
675525
                                             GDBusMethodInvocation *invocation,
675525
                                             const char            *session_name)
675525
 {
675525
         GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
675525
         g_debug ("GdmSessionWorker: session name set to %s", session_name);
675525
         gdm_session_settings_set_session_name (worker->priv->user_settings,
675525
                                                session_name);
675525
         gdm_dbus_worker_complete_set_session_name (object, invocation);
675525
         return TRUE;
675525
@@ -2639,61 +2651,61 @@ do_authorize (GdmSessionWorker *worker)
675525
                 g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error);
675525
         }
675525
         worker->priv->pending_invocation = NULL;
675525
 }
675525
 
675525
 static void
675525
 do_accredit (GdmSessionWorker *worker)
675525
 {
675525
         GError  *error;
675525
         gboolean res;
675525
 
675525
         /* get kerberos tickets, setup group lists, etc
675525
          */
675525
         error = NULL;
675525
         res = gdm_session_worker_accredit_user (worker, &error);
675525
 
675525
         if (res) {
675525
                 gdm_dbus_worker_complete_establish_credentials (GDM_DBUS_WORKER (worker), worker->priv->pending_invocation);
675525
         } else {
675525
                 g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error);
675525
         }
675525
         worker->priv->pending_invocation = NULL;
675525
 }
675525
 
675525
 static void
675525
 save_account_details_now (GdmSessionWorker *worker)
675525
 {
675525
         g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCREDITED);
675525
 
675525
         g_debug ("GdmSessionWorker: saving account details for user %s", worker->priv->username);
675525
-        worker->priv->state = GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED;
675525
+        gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
675525
         if (!gdm_session_settings_save (worker->priv->user_settings,
675525
                                         worker->priv->username)) {
675525
                 g_warning ("could not save session and language settings");
675525
         }
675525
         queue_state_change (worker);
675525
 }
675525
 
675525
 static void
675525
 on_settings_is_loaded_changed (GdmSessionSettings *user_settings,
675525
                                GParamSpec         *pspec,
675525
                                GdmSessionWorker   *worker)
675525
 {
675525
         if (!gdm_session_settings_is_loaded (worker->priv->user_settings)) {
675525
                 return;
675525
         }
675525
 
675525
         /* These signal handlers should be disconnected after the loading,
675525
          * so that gdm_session_settings_set_* APIs don't cause the emitting
675525
          * of Saved*NameRead D-Bus signals any more.
675525
          */
675525
         g_signal_handlers_disconnect_by_func (worker->priv->user_settings,
675525
                                               G_CALLBACK (on_saved_session_name_read),
675525
                                               worker);
675525
 
675525
         g_signal_handlers_disconnect_by_func (worker->priv->user_settings,
675525
                                               G_CALLBACK (on_saved_language_name_read),
675525
                                               worker);
675525
 
675525
         if (worker->priv->state == GDM_SESSION_WORKER_STATE_NONE) {
675525
                 g_debug ("GdmSessionWorker: queuing setup for user: %s %s",
675525
@@ -3443,60 +3455,68 @@ worker_interface_init (GdmDBusWorkerIface *interface)
675525
         interface->handle_start_reauthentication = gdm_session_worker_handle_start_reauthentication;
675525
 }
675525
 
675525
 static void
675525
 gdm_session_worker_class_init (GdmSessionWorkerClass *klass)
675525
 {
675525
         GObjectClass    *object_class = G_OBJECT_CLASS (klass);
675525
 
675525
         object_class->get_property = gdm_session_worker_get_property;
675525
         object_class->set_property = gdm_session_worker_set_property;
675525
         object_class->constructor = gdm_session_worker_constructor;
675525
         object_class->finalize = gdm_session_worker_finalize;
675525
 
675525
         g_type_class_add_private (klass, sizeof (GdmSessionWorkerPrivate));
675525
 
675525
         g_object_class_install_property (object_class,
675525
                                          PROP_SERVER_ADDRESS,
675525
                                          g_param_spec_string ("server-address",
675525
                                                               "server address",
675525
                                                               "server address",
675525
                                                               NULL,
675525
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
675525
 
675525
         g_object_class_install_property (object_class,
675525
                                          PROP_IS_REAUTH_SESSION,
675525
                                          g_param_spec_boolean ("is-reauth-session",
675525
                                                                "is reauth session",
675525
                                                                "is reauth session",
675525
                                                               FALSE,
675525
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
675525
+        g_object_class_install_property (object_class,
675525
+                                         PROP_STATE,
675525
+                                         g_param_spec_enum ("state",
675525
+                                                            "state",
675525
+                                                            "state",
675525
+                                                            GDM_TYPE_SESSION_WORKER_STATE,
675525
+                                                            GDM_SESSION_WORKER_STATE_NONE,
675525
+                                                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
675525
 }
675525
 
675525
 static void
675525
 reauthentication_request_free (ReauthenticationRequest *request)
675525
 {
675525
 
675525
         g_signal_handlers_disconnect_by_func (request->session,
675525
                                               G_CALLBACK (on_reauthentication_client_connected),
675525
                                               request);
675525
         g_signal_handlers_disconnect_by_func (request->session,
675525
                                               G_CALLBACK (on_reauthentication_client_disconnected),
675525
                                               request);
675525
         g_signal_handlers_disconnect_by_func (request->session,
675525
                                               G_CALLBACK (on_reauthentication_cancelled),
675525
                                               request);
675525
         g_signal_handlers_disconnect_by_func (request->session,
675525
                                               G_CALLBACK (on_reauthentication_conversation_started),
675525
                                               request);
675525
         g_signal_handlers_disconnect_by_func (request->session,
675525
                                               G_CALLBACK (on_reauthentication_conversation_stopped),
675525
                                               request);
675525
         g_signal_handlers_disconnect_by_func (request->session,
675525
                                               G_CALLBACK (on_reauthentication_verification_complete),
675525
                                               request);
675525
         g_clear_object (&request->session);
675525
         g_slice_free (ReauthenticationRequest, request);
675525
 }
675525
 
675525
 static void
675525
 gdm_session_worker_init (GdmSessionWorker *worker)
675525
diff --git a/daemon/session-worker-main.c b/daemon/session-worker-main.c
675525
index 4a3a8ebbe..d96844d2d 100644
675525
--- a/daemon/session-worker-main.c
675525
+++ b/daemon/session-worker-main.c
675525
@@ -37,104 +37,137 @@
675525
 #include <glib-object.h>
675525
 
675525
 #include "gdm-common.h"
675525
 #include "gdm-log.h"
675525
 #include "gdm-session-worker.h"
675525
 
675525
 #include "gdm-settings.h"
675525
 #include "gdm-settings-direct.h"
675525
 #include "gdm-settings-keys.h"
675525
 
675525
 static GdmSettings *settings = NULL;
675525
 
675525
 static gboolean
675525
 on_sigusr1_cb (gpointer user_data)
675525
 {
675525
         g_debug ("Got USR1 signal");
675525
 
675525
         gdm_log_toggle_debug ();
675525
 
675525
         return TRUE;
675525
 }
675525
 
675525
 static gboolean
675525
 is_debug_set (void)
675525
 {
675525
         gboolean debug;
675525
         gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
675525
         return debug;
675525
 }
675525
 
675525
+static gboolean
675525
+on_shutdown_signal_cb (gpointer user_data)
675525
+{
675525
+        GMainLoop *mainloop = user_data;
675525
+
675525
+        g_main_loop_quit (mainloop);
675525
+
675525
+        return FALSE;
675525
+}
675525
+
675525
+static void
675525
+on_state_changed (GdmSessionWorker *worker,
675525
+                  GParamSpec       *pspec,
675525
+                  GMainLoop        *main_loop)
675525
+{
675525
+        GdmSessionWorkerState state;
675525
+
675525
+        g_object_get (G_OBJECT (worker), "state", &state, NULL);
675525
+
675525
+        if (state != GDM_SESSION_WORKER_STATE_SESSION_STARTED)
675525
+                return;
675525
+
675525
+        g_unix_signal_add (SIGTERM, on_shutdown_signal_cb, main_loop);
675525
+}
675525
+
675525
 static void
675525
 on_sigterm_cb (int signal_number)
675525
 {
675525
         _exit (EXIT_SUCCESS);
675525
 }
675525
 
675525
 int
675525
 main (int    argc,
675525
       char **argv)
675525
 {
675525
         GMainLoop        *main_loop;
675525
         GOptionContext   *context;
675525
         GdmSessionWorker *worker;
675525
         const char       *address;
675525
         gboolean          is_for_reauth;
675525
         static GOptionEntry entries []   = {
675525
                 { NULL }
675525
         };
675525
 
675525
         signal (SIGTERM, on_sigterm_cb);
675525
 
675525
         bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
675525
         textdomain (GETTEXT_PACKAGE);
675525
         setlocale (LC_ALL, "");
675525
 
675525
         /* Translators: worker is a helper process that does the work
675525
            of starting up a session */
675525
         context = g_option_context_new (_("GNOME Display Manager Session Worker"));
675525
         g_option_context_add_main_entries (context, entries, NULL);
675525
 
675525
         g_option_context_parse (context, &argc, &argv, NULL);
675525
         g_option_context_free (context);
675525
 
675525
         gdm_log_init ();
675525
 
675525
         settings = gdm_settings_new ();
675525
         if (settings == NULL) {
675525
                 g_warning ("Unable to initialize settings");
675525
                 exit (EXIT_FAILURE);
675525
         }
675525
 
675525
         if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) {
675525
                 g_warning ("Unable to initialize settings");
675525
                 exit (EXIT_FAILURE);
675525
         }
675525
 
675525
         gdm_log_set_debug (is_debug_set ());
675525
 
675525
         address = g_getenv ("GDM_SESSION_DBUS_ADDRESS");
675525
         if (address == NULL) {
675525
                 g_warning ("GDM_SESSION_DBUS_ADDRESS not set");
675525
                 exit (EXIT_FAILURE);
675525
         }
675525
 
675525
         is_for_reauth = g_getenv ("GDM_SESSION_FOR_REAUTH") != NULL;
675525
 
675525
         worker = gdm_session_worker_new (address, is_for_reauth);
675525
 
675525
         main_loop = g_main_loop_new (NULL, FALSE);
675525
 
675525
+        g_signal_connect (G_OBJECT (worker),
675525
+                          "notify::state",
675525
+                          G_CALLBACK (on_state_changed),
675525
+                          main_loop);
675525
+
675525
         g_unix_signal_add (SIGUSR1, on_sigusr1_cb, NULL);
675525
 
675525
         g_main_loop_run (main_loop);
675525
 
675525
         if (worker != NULL) {
675525
+                g_signal_handlers_disconnect_by_func (worker,
675525
+                                                      G_CALLBACK (on_state_changed),
675525
+                                                      main_loop);
675525
                 g_object_unref (worker);
675525
         }
675525
 
675525
         g_main_loop_unref (main_loop);
675525
 
675525
         g_debug ("Worker finished");
675525
 
675525
         return 0;
675525
 }
675525
-- 
675525
2.21.0
675525