[libsecret] Disconnect the cached default SecretService if service goes away
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsecret] Disconnect the cached default SecretService if service goes away
- Date: Fri, 6 Jul 2012 09:50:31 +0000 (UTC)
commit 175ae0898446de247530de47ae2a4edc0340e08e
Author: Stef Walter <stefw gnome org>
Date: Fri Jul 6 10:08:27 2012 +0200
Disconnect the cached default SecretService if service goes away
* Because the session would no longer be valid if the service
was autostarted for the same SecretService proxy
docs/reference/libsecret/libsecret-sections.txt | 1 +
library/secret-service.c | 116 +++++++++++++++++------
library/tests/mock-service.c | 1 +
library/tests/test-password.c | 1 -
4 files changed, 88 insertions(+), 31 deletions(-)
---
diff --git a/docs/reference/libsecret/libsecret-sections.txt b/docs/reference/libsecret/libsecret-sections.txt
index 3fbba6c..bd45c41 100644
--- a/docs/reference/libsecret/libsecret-sections.txt
+++ b/docs/reference/libsecret/libsecret-sections.txt
@@ -174,6 +174,7 @@ SecretServiceFlags
secret_service_get
secret_service_get_sync
secret_service_get_finish
+secret_service_disconnect
secret_service_new
secret_service_new_finish
secret_service_new_sync
diff --git a/library/secret-service.c b/library/secret-service.c
index b56c334..658b04d 100644
--- a/library/secret-service.c
+++ b/library/secret-service.c
@@ -124,6 +124,7 @@ struct _SecretServicePrivate {
G_LOCK_DEFINE (service_instance);
static gpointer service_instance = NULL;
+static guint service_watch = 0;
static GInitableIface *secret_service_initable_parent_iface = NULL;
@@ -138,6 +139,84 @@ G_DEFINE_TYPE_WITH_CODE (SecretService, secret_service, G_TYPE_DBUS_PROXY,
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, secret_service_async_initable_iface);
);
+static SecretService *
+service_get_instance (void)
+{
+ SecretService *instance = NULL;
+
+ G_LOCK (service_instance);
+ if (service_instance != NULL)
+ instance = g_object_ref (service_instance);
+ G_UNLOCK (service_instance);
+
+ return instance;
+}
+
+static gboolean
+service_uncache_instance (SecretService *which)
+{
+ SecretService *instance = NULL;
+ guint watch = 0;
+ gboolean matched = FALSE;
+
+ G_LOCK (service_instance);
+ if (which == NULL || service_instance == which) {
+ instance = service_instance;
+ service_instance = NULL;
+ watch = service_watch;
+ service_watch = 0;
+ matched = TRUE;
+ }
+ G_UNLOCK (service_instance);
+
+ if (instance != NULL)
+ g_object_unref (instance);
+ if (watch != 0)
+ g_bus_unwatch_name (watch);
+
+ return matched;
+}
+
+static void
+on_service_instance_vanished (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ if (!service_uncache_instance (user_data)) {
+ g_warning ("Global default SecretService instance out of sync "
+ "with the watch for its DBus name");
+ }
+}
+
+static void
+service_cache_instance (SecretService *instance)
+{
+ GDBusProxy *proxy;
+ guint watch;
+
+ g_object_ref (instance);
+ proxy = G_DBUS_PROXY (instance);
+ watch = g_bus_watch_name_on_connection (g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+ NULL, on_service_instance_vanished,
+ instance, NULL);
+
+ G_LOCK (service_instance);
+ if (service_instance == NULL) {
+ service_instance = instance;
+ instance = NULL;
+ service_watch = watch;
+ watch = 0;
+ }
+ G_UNLOCK (service_instance);
+
+ if (instance != NULL)
+ g_object_unref (instance);
+ if (watch != 0)
+ g_bus_unwatch_name (watch);
+}
+
static void
secret_service_init (SecretService *self)
{
@@ -678,10 +757,7 @@ secret_service_get (SecretServiceFlags flags,
GSimpleAsyncResult *res;
InitClosure *closure;
- G_LOCK (service_instance);
- if (service_instance != NULL)
- service = g_object_ref (service_instance);
- G_UNLOCK (service_instance);
+ service = service_get_instance ();
/* Create a whole new service */
if (service == NULL) {
@@ -743,13 +819,8 @@ secret_service_get_finish (GAsyncResult *result,
/* Creating a whole new service */
} else {
service = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
-
- if (service) {
- G_LOCK (service_instance);
- if (service_instance == NULL)
- service_instance = g_object_ref (service);
- G_UNLOCK (service_instance);
- }
+ if (service)
+ service_cache_instance (SECRET_SERVICE (service));
}
if (source_object)
@@ -786,10 +857,7 @@ secret_service_get_sync (SecretServiceFlags flags,
{
SecretService *service = NULL;
- G_LOCK (service_instance);
- if (service_instance != NULL)
- service = g_object_ref (service_instance);
- G_UNLOCK (service_instance);
+ service = service_get_instance ();
if (service == NULL) {
service = g_initable_new (SECRET_TYPE_SERVICE, cancellable, error,
@@ -802,12 +870,8 @@ secret_service_get_sync (SecretServiceFlags flags,
"flags", flags,
NULL);
- if (service != NULL) {
- G_LOCK (service_instance);
- if (service_instance == NULL)
- service_instance = g_object_ref (service);
- G_UNLOCK (service_instance);
- }
+ if (service != NULL)
+ service_cache_instance (service);
} else {
if (!service_ensure_for_flags_sync (service, flags, cancellable, error)) {
@@ -835,15 +899,7 @@ secret_service_get_sync (SecretServiceFlags flags,
void
secret_service_disconnect (void)
{
- SecretService *instance;
-
- G_LOCK (service_instance);
- instance = service_instance;
- service_instance = NULL;
- G_UNLOCK (service_instance);
-
- if (instance != NULL)
- g_object_unref (instance);
+ service_uncache_instance (NULL);
}
/**
diff --git a/library/tests/mock-service.c b/library/tests/mock-service.c
index feb6690..6a5a0f6 100644
--- a/library/tests/mock-service.c
+++ b/library/tests/mock-service.c
@@ -88,5 +88,6 @@ mock_service_stop (void)
}
g_spawn_close_pid (pid);
+ secret_service_disconnect ();
pid = 0;
}
diff --git a/library/tests/test-password.c b/library/tests/test-password.c
index d541daf..d5829df 100644
--- a/library/tests/test-password.c
+++ b/library/tests/test-password.c
@@ -74,7 +74,6 @@ static void
teardown (Test *test,
gconstpointer unused)
{
- secret_service_disconnect ();
mock_service_stop ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]