diff --git a/daemon/gdm-display-store.c b/daemon/gdm-display-store.c
index fd24334..8c1ae25 100644
--- a/daemon/gdm-display-store.c
+++ b/daemon/gdm-display-store.c
@@ -136,6 +136,35 @@ typedef struct
         gpointer            user_data;
 } FindClosure;
 
+static void
+copy_func (StoredDisplay *stored_display,
+           FindClosure   *closure)
+{
+        closure->user_data = g_list_append (closure->user_data,
+                                            stored_display->display);
+}
+
+GList *
+gdm_display_store_get_displays (GdmDisplayStore    *store)
+{
+        GList *displays = NULL;
+        GList *store_displays = NULL;
+        FindClosure  closure;
+        g_return_val_if_fail (store != NULL, NULL);
+
+        store_displays = g_hash_table_get_values (store->priv->displays);
+
+        closure.user_data = displays;
+
+        g_list_foreach (store_displays,
+                        (GFunc) copy_func,
+                        &closure);
+        displays = closure.user_data;
+
+        g_list_free (store_displays);
+        return displays;
+}
+
 static gboolean
 find_func (const char    *id,
            StoredDisplay *stored_display,
diff --git a/daemon/gdm-display-store.h b/daemon/gdm-display-store.h
index 0aff8ee..cd69518 100644
--- a/daemon/gdm-display-store.h
+++ b/daemon/gdm-display-store.h
@@ -86,6 +86,8 @@ GdmDisplay *        gdm_display_store_find                     (GdmDisplayStore
                                                                 GdmDisplayStoreFunc predicate,
                                                                 gpointer            user_data);
 
+GList *             gdm_display_store_get_displays             (GdmDisplayStore    *store);
+
 
 G_END_DECLS
 
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index cb9f662..a971ba3 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -2703,9 +2703,7 @@ unexport_display (const char *id,
 }
 
 static void
-finish_display (const char *id,
-                GdmDisplay *display,
-                GdmManager *manager)
+finish_display (GdmDisplay *display)
 {
         gdm_display_stop_greeter_session (display);
         if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED)
@@ -2717,6 +2715,7 @@ static void
 gdm_manager_dispose (GObject *object)
 {
         GdmManager *manager;
+        GList      *displays = NULL;
 
         g_return_if_fail (object != NULL);
         g_return_if_fail (GDM_IS_MANAGER (object));
@@ -2758,9 +2757,11 @@ gdm_manager_dispose (GObject *object)
                 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (manager));
         }
 
-        gdm_display_store_foreach (manager->priv->display_store,
-                                   (GdmDisplayStoreFunc) finish_display,
-                                   manager);
+        displays = gdm_display_store_get_displays (manager->priv->display_store);
+        g_list_foreach (displays,
+                        (GFunc) finish_display,
+                        NULL);
+        g_list_free (displays);
 
         gdm_display_store_clear (manager->priv->display_store);
 
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 06e5a6a..07642cd 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -34,6 +34,7 @@
 #include <errno.h>
 #include <grp.h>
 #include <pwd.h>
+#include <signal.h>
 
 #include <security/pam_appl.h>
 
@@ -181,6 +182,8 @@ struct GdmSessionWorkerPrivate
         GdmSessionSettings *user_settings;
 
         GDBusMethodInvocation *pending_invocation;
+
+        GMainLoop          *main_loop;
 };
 
 #ifdef SUPPORTS_PAM_EXTENSIONS
@@ -197,6 +200,7 @@ enum {
         PROP_0,
         PROP_SERVER_ADDRESS,
         PROP_IS_REAUTH_SESSION,
+        PROP_MAIN_LOOP,
 };
 
 static void     gdm_session_worker_class_init   (GdmSessionWorkerClass *klass);
@@ -2455,6 +2459,13 @@ gdm_session_worker_set_is_reauth_session (GdmSessionWorker *worker,
         worker->priv->is_reauth_session = is_reauth_session;
 }
 
+static void
+gdm_session_worker_set_main_loop (GdmSessionWorker *worker,
+                                  GMainLoop        *main_loop)
+{
+        worker->priv->main_loop = main_loop;
+}
+
 static void
 gdm_session_worker_set_property (GObject      *object,
                                 guint         prop_id,
@@ -2472,6 +2483,9 @@ gdm_session_worker_set_property (GObject      *object,
         case PROP_IS_REAUTH_SESSION:
                 gdm_session_worker_set_is_reauth_session (self, g_value_get_boolean (value));
                 break;
+        case PROP_MAIN_LOOP:
+                gdm_session_worker_set_main_loop (self, g_value_get_pointer (value));
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -2495,6 +2509,9 @@ gdm_session_worker_get_property (GObject    *object,
         case PROP_IS_REAUTH_SESSION:
                 g_value_set_boolean (value, self->priv->is_reauth_session);
                 break;
+        case PROP_MAIN_LOOP:
+                g_value_set_pointer (value, self->priv->main_loop);
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -2764,6 +2781,16 @@ do_open_session (GdmSessionWorker *worker)
         worker->priv->pending_invocation = NULL;
 }
 
+static gboolean
+on_shutdown_signal_cb (gpointer user_data)
+{
+        GMainLoop *mainloop = user_data;
+
+        g_main_loop_quit (mainloop);
+
+        return FALSE;
+}
+
 static void
 do_start_session (GdmSessionWorker *worker)
 {
@@ -2773,6 +2800,9 @@ do_start_session (GdmSessionWorker *worker)
         error = NULL;
         res = gdm_session_worker_start_session (worker, &error);
         if (res) {
+                g_unix_signal_add (SIGTERM, on_shutdown_signal_cb, worker->priv->main_loop);
+                g_unix_signal_add (SIGINT, on_shutdown_signal_cb,  worker->priv->main_loop);
+
                 gdm_dbus_worker_complete_start_program (GDM_DBUS_WORKER (worker),
                                                         worker->priv->pending_invocation,
                                                         worker->priv->child_pid);
@@ -3471,6 +3501,13 @@ gdm_session_worker_class_init (GdmSessionWorkerClass *klass)
                                                                "is reauth session",
                                                               FALSE,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+        g_object_class_install_property (object_class,
+                                         PROP_MAIN_LOOP,
+                                         g_param_spec_pointer ("main-loop",
+                                                               "main loop",
+                                                               "main loop",
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
 
 static void
@@ -3561,13 +3598,15 @@ gdm_session_worker_finalize (GObject *object)
 
 GdmSessionWorker *
 gdm_session_worker_new (const char *address,
-                        gboolean    is_reauth_session)
+                        gboolean    is_reauth_session,
+                        GMainLoop   *main_loop)
 {
         GObject *object;
 
         object = g_object_new (GDM_TYPE_SESSION_WORKER,
                                "server-address", address,
                                "is-reauth-session", is_reauth_session,
+                               "main-loop", main_loop,
                                NULL);
 
         return GDM_SESSION_WORKER (object);
diff --git a/daemon/gdm-session-worker.h b/daemon/gdm-session-worker.h
index 5603e80..24979e4 100644
--- a/daemon/gdm-session-worker.h
+++ b/daemon/gdm-session-worker.h
@@ -51,6 +51,7 @@ typedef struct
 GType              gdm_session_worker_get_type                 (void);
 
 GdmSessionWorker * gdm_session_worker_new                      (const char *server_address,
-                                                                gboolean    is_for_reauth) G_GNUC_MALLOC;
+                                                                gboolean    is_for_reauth,
+                                                                GMainLoop  *main_loop) G_GNUC_MALLOC;
 G_END_DECLS
 #endif /* GDM_SESSION_WORKER_H */
diff --git a/daemon/session-worker-main.c b/daemon/session-worker-main.c
index 4a3a8eb..da3e7c6 100644
--- a/daemon/session-worker-main.c
+++ b/daemon/session-worker-main.c
@@ -64,12 +64,6 @@ is_debug_set (void)
         return debug;
 }
 
-static void
-on_sigterm_cb (int signal_number)
-{
-        _exit (EXIT_SUCCESS);
-}
-
 int
 main (int    argc,
       char **argv)
@@ -83,8 +77,6 @@ main (int    argc,
                 { NULL }
         };
 
-        signal (SIGTERM, on_sigterm_cb);
-
         bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
         textdomain (GETTEXT_PACKAGE);
         setlocale (LC_ALL, "");
@@ -120,10 +112,10 @@ main (int    argc,
 
         is_for_reauth = g_getenv ("GDM_SESSION_FOR_REAUTH") != NULL;
 
-        worker = gdm_session_worker_new (address, is_for_reauth);
-
         main_loop = g_main_loop_new (NULL, FALSE);
 
+        worker = gdm_session_worker_new (address, is_for_reauth, main_loop);
+
         g_unix_signal_add (SIGUSR1, on_sigusr1_cb, NULL);
 
         g_main_loop_run (main_loop);
