From bf8d119a0ef9ae2a708943d0c241b719bc9b18e6 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 22 Feb 2011 22:41:12 +0900 Subject: [PATCH] Make sure to remove context from the stack if the client is disconnected. --- src/server-server.c | 65 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/src/server-server.c b/src/server-server.c index e0395494..39aa1b07 100644 --- a/src/server-server.c +++ b/src/server-server.c @@ -58,6 +58,7 @@ struct _ServerServer { GHashTable *context_hash; GSList *context_stack; + GHashTable *sender_object_path_hash; }; struct _ServerServerClass { @@ -122,6 +123,11 @@ server_server_dispose (GObject *object) server->context_hash = NULL; } + if (server->sender_object_path_hash) { + g_hash_table_destroy (server->sender_object_path_hash); + server->sender_object_path_hash = NULL; + } + for (head = server->context_stack; head; head = server->context_stack) { g_object_unref (head->data); server->context_stack = g_slist_next (head); @@ -212,6 +218,45 @@ server_server_init (ServerServer *server) (GDestroyNotify)g_free, (GDestroyNotify)g_object_unref); server->context_stack = NULL; + server->sender_object_path_hash = + g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify)g_free, + NULL); +} + +static void +remove_context_from_stack (ServerServer *server, ServerContext *context) +{ + GSList *head; + + head = g_slist_find (server->context_stack, context); + if (head) { + server->context_stack = g_slist_remove_link (server->context_stack, + head); + g_slist_free1 (head); + g_object_unref (context); + } +} + +static void +server_name_vanished_callback (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + ServerServer *server = user_data; + const gchar *object_path; + + object_path = g_hash_table_lookup (server->sender_object_path_hash, name); + if (object_path) { + ServerContext *context; + + context = g_hash_table_lookup (server->context_hash, object_path); + if (context) { + remove_context_from_stack (server, context); + g_hash_table_remove (server->context_hash, object_path); + } + } } static void @@ -238,6 +283,16 @@ handle_method_call (GDBusConnection *connection, g_hash_table_insert (server->context_hash, object_path, context); + g_hash_table_insert (server->sender_object_path_hash, + g_strdup (sender), + object_path); + g_bus_watch_name_on_connection (server->connection, + sender, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + server_name_vanished_callback, + server, + NULL); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", object_path)); @@ -286,7 +341,6 @@ handle_method_call (GDBusConnection *connection, if (g_strcmp0 (method_name, "DestroyContext") == 0) { const gchar *object_path; ServerContext *context; - GSList *head; g_variant_get (parameters, "(&s)", &object_path); context = g_hash_table_lookup (server->context_hash, object_path); @@ -297,15 +351,8 @@ handle_method_call (GDBusConnection *connection, "context not found"); return; } - head = g_slist_find (server->context_stack, context); - if (head) { - server->context_stack = g_slist_remove_link (server->context_stack, - head); - g_slist_free1 (head); - } - + remove_context_from_stack (server, context); g_hash_table_remove (server->context_hash, object_path); - g_dbus_method_invocation_return_value (invocation, NULL); return; }