[gnome-keyring] daemon: Exit gnome-keyring-daemon when the DBus connection closes
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring] daemon: Exit gnome-keyring-daemon when the DBus connection closes
- Date: Thu, 6 Mar 2014 17:47:46 +0000 (UTC)
commit 636113849f970af6819ef599d207419c4881f8fb
Author: Stef Walter <stefw gnome org>
Date: Thu Mar 6 16:11:12 2014 +0100
daemon: Exit gnome-keyring-daemon when the DBus connection closes
We don't do this via the standard mechanism, as it means that libdbus
just calls _exit() (not even exit()) when the connection goes away.
This can lead to inconsistent state. Shutdown should be orderly.
https://bugzilla.gnome.org/show_bug.cgi?id=708765
daemon/Makefile.am | 7 +++-
daemon/dbus/gkd-dbus.c | 10 ++++-
daemon/gkd-main.c | 4 +-
daemon/test-shutdown.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++
egg/egg-dbus.c | 21 +++++++--
egg/egg-dbus.h | 4 +-
6 files changed, 152 insertions(+), 9 deletions(-)
---
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index bcfff8c..e9c4a18 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -76,11 +76,16 @@ daemon_LIBS = \
$(GLIB_LIBS)
daemon_TESTS = \
- test-startup
+ test-startup \
+ test-shutdown
test_startup_SOURCES = daemon/test-startup.c
test_startup_LDADD = $(daemon_LIBS)
test_statrup_CFLAGS = $(daemon_CFLAGS)
+test_shutdown_SOURCES = daemon/test-shutdown.c
+test_shutdown_LDADD = $(daemon_LIBS)
+test_shutdown_CFLAGS = $(daemon_CFLAGS)
+
check_PROGRAMS += $(daemon_TESTS)
TESTS += $(daemon_TESTS)
diff --git a/daemon/dbus/gkd-dbus.c b/daemon/dbus/gkd-dbus.c
index b66af10..e13e88d 100644
--- a/daemon/dbus/gkd-dbus.c
+++ b/daemon/dbus/gkd-dbus.c
@@ -25,6 +25,7 @@
#include "gkd-dbus.h"
#include "gkd-dbus-private.h"
+#include "daemon/gkd-main.h"
#include "daemon/gkd-util.h"
#include "egg/egg-cleanup.h"
@@ -54,6 +55,13 @@ cleanup_session_bus (gpointer unused)
dbus_conn = NULL;
}
+static void
+on_connection_close (gpointer user_data)
+{
+ g_debug ("dbus connection closed, exiting");
+ gkd_main_quit ();
+}
+
static gboolean
connect_to_session_bus (void)
{
@@ -72,7 +80,7 @@ connect_to_session_bus (void)
return FALSE;
}
- egg_dbus_connect_with_mainloop (dbus_conn, NULL);
+ egg_dbus_connect_with_mainloop (dbus_conn, NULL, on_connection_close);
dbus_connection_set_exit_on_disconnect (dbus_conn, FALSE);
egg_cleanup_register (cleanup_session_bus, NULL);
return TRUE;
diff --git a/daemon/gkd-main.c b/daemon/gkd-main.c
index 731d205..6664c28 100644
--- a/daemon/gkd-main.c
+++ b/daemon/gkd-main.c
@@ -81,6 +81,8 @@ typedef int socklen_t;
EGG_SECURE_DECLARE (daemon_main);
+static GMainLoop *loop = NULL;
+
/* -----------------------------------------------------------------------------
* COMMAND LINE
*/
@@ -902,8 +904,6 @@ on_idle_initialize (gpointer data)
int
main (int argc, char *argv[])
{
- GMainLoop *loop;
-
/*
* The gnome-keyring startup is not as simple as I wish it could be.
*
diff --git a/daemon/test-shutdown.c b/daemon/test-shutdown.c
new file mode 100644
index 0000000..b2fdb0c
--- /dev/null
+++ b/daemon/test-shutdown.c
@@ -0,0 +1,115 @@
+/*
+ Copyright (C) 2014 Red Hat Inc
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ <http://www.gnu.org/licenses/>.
+
+ Author: Stef Walter <stefw gnome org>
+*/
+
+#include "config.h"
+
+#include "gkd-test.h"
+
+#include "daemon/control/gkd-control.h"
+
+#include "egg/egg-testing.h"
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+
+typedef struct {
+ GTestDBus *dbus;
+ gchar *directory;
+ GPid pid;
+} Test;
+
+static void
+setup (Test *test,
+ gconstpointer unused)
+{
+ test->dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
+ g_test_dbus_up (test->dbus);
+
+ test->directory = egg_tests_create_scratch_directory (NULL, NULL);
+}
+
+static void
+teardown (Test *test,
+ gconstpointer unused)
+{
+ if (test->pid) {
+ if (waitpid (test->pid, NULL, WNOHANG) != test->pid) {
+ kill (test->pid, SIGTERM);
+ g_assert_cmpint (waitpid (test->pid, NULL, 0), ==, test->pid);
+ }
+ g_spawn_close_pid (test->pid);
+ }
+
+ egg_tests_remove_scratch_directory (test->directory);
+ g_free (test->directory);
+
+ if (test->dbus) {
+ g_test_dbus_down (test->dbus);
+ g_object_unref (test->dbus);
+ }
+}
+
+static void
+test_close_connection (Test *test,
+ gconstpointer unused)
+{
+ const gchar *argv[] = {
+ BUILDDIR "/gnome-keyring-daemon", "--foreground",
+ "--components=secrets,pkcs11", NULL
+ };
+
+ const gchar *control;
+ gchar **output;
+ gint status;
+ GPid pid;
+
+ output = gkd_test_launch_daemon (test->directory, argv, &pid, NULL);
+
+ control = g_environ_getenv (output, "GNOME_KEYRING_CONTROL");
+ g_assert_cmpstr (control, !=, NULL);
+
+ g_assert (gkd_control_unlock (control, "booo"));
+ g_strfreev (output);
+
+ /* Now close the dbus connection */
+ g_test_dbus_down (test->dbus);
+ g_object_unref (test->dbus);
+ test->dbus = NULL;
+
+ /* Daemon should exit */
+ g_assert_cmpint (waitpid (pid, &status, 0), ==, pid);
+ g_assert_cmpint (status, ==, 0);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/daemon/shutdown/dbus-connection", Test, NULL,
+ setup, test_close_connection, teardown);
+
+ return g_test_run ();
+}
diff --git a/egg/egg-dbus.c b/egg/egg-dbus.c
index dca3425..b3bfa9e 100644
--- a/egg/egg-dbus.c
+++ b/egg/egg-dbus.c
@@ -37,13 +37,21 @@
typedef struct {
GSource source; /* the parent GSource */
DBusConnection *connection; /* the connection to dispatch */
+ GDestroyNotify closed_cb; /* Callback when closed */
} DBusGMessageQueue;
static gboolean
message_queue_prepare (GSource *source, gint *timeout)
{
- DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+ DBusGMessageQueue *queue = ((DBusGMessageQueue *)source);
+ DBusConnection *connection = queue->connection;
*timeout = -1;
+ if (queue->closed_cb) {
+ if (!dbus_connection_get_is_connected (connection)) {
+ (queue->closed_cb) (connection);
+ queue->closed_cb = NULL;
+ }
+ }
return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
}
@@ -95,7 +103,9 @@ typedef struct {
} TimeoutHandler;
static ConnectionSetup*
-connection_setup_new (GMainContext *context, DBusConnection *connection)
+connection_setup_new (GMainContext *context,
+ DBusConnection *connection,
+ GDestroyNotify closed_cb)
{
ConnectionSetup *cs = g_new0 (ConnectionSetup, 1);
g_assert (context != NULL);
@@ -108,6 +118,7 @@ connection_setup_new (GMainContext *context, DBusConnection *connection)
cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
sizeof (DBusGMessageQueue));
((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
+ ((DBusGMessageQueue*)cs->message_queue_source)->closed_cb = closed_cb;
g_source_attach (cs->message_queue_source, cs->context);
}
@@ -368,13 +379,15 @@ wakeup_main (void *data)
}
void
-egg_dbus_connect_with_mainloop (DBusConnection *connection, GMainContext *context)
+egg_dbus_connect_with_mainloop (DBusConnection *connection,
+ GMainContext *context,
+ GDestroyNotify close_callback)
{
ConnectionSetup *cs;
if (context == NULL)
context = g_main_context_default ();
- cs = connection_setup_new (context, connection);
+ cs = connection_setup_new (context, connection, close_callback);
the_setup = cs;
if (!dbus_connection_set_watch_functions (connection, add_watch,
diff --git a/egg/egg-dbus.h b/egg/egg-dbus.h
index 81dc2e9..91b7ab3 100644
--- a/egg/egg-dbus.h
+++ b/egg/egg-dbus.h
@@ -27,7 +27,9 @@
#include <glib.h>
#include <dbus/dbus.h>
-void egg_dbus_connect_with_mainloop (DBusConnection *connection, GMainContext *context);
+void egg_dbus_connect_with_mainloop (DBusConnection *connection,
+ GMainContext *context,
+ GDestroyNotify close_callback);
void egg_dbus_disconnect_from_mainloop (DBusConnection *connection, GMainContext *context);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]