[grilo] core: Add grl_deinit() function
- From: Juan A. Suarez Romero <jasuarez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grilo] core: Add grl_deinit() function
- Date: Sun, 9 Feb 2014 02:01:44 +0000 (UTC)
commit 27fa2aa1f9201d4f0723afe43e90cd996876c999
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date: Fri Feb 7 20:47:32 2014 +0000
core: Add grl_deinit() function
Quitting without cleanly unregistering sources and plugins can leave unfreed
resources in the system.
This happens specially with the sources that open or create temporal files, but
as they are not cleanly unreffed the files are kept there.
So we are adding grl_deinit() function, which should be called by the
applications once they have finished to use Grilo. This function will cleanly
unload all the sources and plugins.
https://bugzilla.gnome.org/show_bug.cgi?id=710185
doc/grilo/grilo-sections.txt | 1 +
src/grilo.c | 25 ++++++++++
src/grilo.h | 2 +
src/grl-registry.c | 104 +++++++++++++++++++++++++++++++++++++++---
4 files changed, 125 insertions(+), 7 deletions(-)
---
diff --git a/doc/grilo/grilo-sections.txt b/doc/grilo/grilo-sections.txt
index 26b5550..c99e9fd 100644
--- a/doc/grilo/grilo-sections.txt
+++ b/doc/grilo/grilo-sections.txt
@@ -684,6 +684,7 @@ grl_paging_translate
<FILE>grilo</FILE>
grl_init
grl_init_get_option_group
+grl_deinit
</SECTION>
<SECTION>
diff --git a/src/grilo.c b/src/grilo.c
index 2ea8bf3..12c7230 100644
--- a/src/grilo.c
+++ b/src/grilo.c
@@ -31,6 +31,9 @@
* The Grilo library should be initialized with grl_init() before it can be used.
* You should pass pointers to the main argc and argv variables so that Grilo can
* process its own command line options.
+ *
+ * After using it, in order to close cleanly all the resources opened either by
+ * the core library or the sources, call grl_deinit().
*/
#include "grilo.h"
@@ -158,6 +161,28 @@ grl_init (gint *argc,
}
/**
+ * grl_deinit:
+ *
+ * Deinitializes the Grilo library.
+ *
+ * Call this function after finalizing using Grilo, in order to free and clean
+ * up all the resources created.
+ */
+void
+grl_deinit (void)
+{
+ GrlRegistry *registry;
+
+ if (!grl_initialized) {
+ GRL_WARNING ("Grilo has not been initialized");
+ return;
+ }
+
+ registry = grl_registry_get_default ();
+ g_object_unref (registry);
+}
+
+/**
* grl_init_get_option_group: (skip)
*
* Returns a #GOptionGroup with Grilo's argument specifications.
diff --git a/src/grilo.h b/src/grilo.h
index af21712..436038b 100644
--- a/src/grilo.h
+++ b/src/grilo.h
@@ -52,6 +52,8 @@ G_BEGIN_DECLS
void grl_init (gint *argc, gchar **argv[]);
+void grl_deinit (void);
+
GOptionGroup *grl_init_get_option_group (void);
G_END_DECLS
diff --git a/src/grl-registry.c b/src/grl-registry.c
index 1488a54..388aaba 100644
--- a/src/grl-registry.c
+++ b/src/grl-registry.c
@@ -87,6 +87,8 @@ struct _GrlRegistryPrivate {
struct KeyIDHandler key_id_handler;
};
+static void grl_registry_finalize (GObject *object);
+
static void grl_registry_setup_ranks (GrlRegistry *registry);
static void grl_registry_preload_plugins (GrlRegistry *registry,
@@ -94,6 +96,8 @@ static void grl_registry_preload_plugins (GrlRegistry *registry,
static void key_id_handler_init (struct KeyIDHandler *handler);
+static void key_id_handler_free (struct KeyIDHandler *handler);
+
static GrlKeyID key_id_handler_get_key (struct KeyIDHandler *handler,
const gchar *key_name);
@@ -103,6 +107,8 @@ static const gchar *key_id_handler_get_name (struct KeyIDHandler *handler,
static GrlKeyID key_id_handler_add (struct KeyIDHandler *handler,
GrlKeyID key, const gchar *key_name);
+static void shutdown_plugin (GrlPlugin *plugin);
+
/* ================ GrlRegistry GObject ================ */
enum {
@@ -117,8 +123,14 @@ G_DEFINE_TYPE (GrlRegistry, grl_registry, G_TYPE_OBJECT);
static void
grl_registry_class_init (GrlRegistryClass *klass)
{
+ GObjectClass *gobject_klass;
+
g_type_class_add_private (klass, sizeof (GrlRegistryPrivate));
+ gobject_klass = G_OBJECT_CLASS (klass);
+
+ gobject_klass->finalize = grl_registry_finalize;
+
/**
* GrlRegistry::source-added:
* @registry: the registry
@@ -179,6 +191,70 @@ grl_registry_init (GrlRegistry *registry)
grl_registry_setup_ranks (registry);
}
+static void
+grl_registry_finalize (GObject *object)
+{
+ GHashTableIter iter;
+ GList *each_key;
+ GList *related_keys = NULL;
+ GrlPlugin *plugin = NULL;
+ GrlRegistry *registry = GRL_REGISTRY (object);
+ GrlSource *source = NULL;
+
+ if (registry->priv->sources) {
+ g_hash_table_iter_init (&iter, registry->priv->sources);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &source)) {
+ g_object_unref (source);
+ }
+ g_hash_table_unref (registry->priv->sources);
+ registry->priv->sources = NULL;
+ }
+
+ if (registry->priv->plugins) {
+ g_hash_table_iter_init (&iter, registry->priv->plugins);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &plugin)) {
+ shutdown_plugin (plugin);
+ }
+ g_hash_table_unref (registry->priv->plugins);
+ registry->priv->plugins = NULL;
+ }
+
+ if (registry->priv->ranks) {
+ g_hash_table_unref (registry->priv->ranks);
+ registry->priv->configs = NULL;
+ }
+
+ if (registry->priv->configs) {
+ g_hash_table_unref (registry->priv->configs);
+ registry->priv->configs = NULL;
+ }
+
+ /* We need to free this table with care. Several keys can be pointing to the
+ same value, so we need to ensure that we only free the value once */
+ if (registry->priv->related_keys) {
+ while (TRUE) {
+ g_hash_table_iter_init (&iter, registry->priv->related_keys);
+ if (!g_hash_table_iter_next (&iter, NULL, (gpointer *) &related_keys)) {
+ break;
+ }
+ /* This will invalidate the iterator */
+ for (each_key = related_keys; each_key; each_key = g_list_next (each_key)) {
+ g_hash_table_remove (registry->priv->related_keys, GRLKEYID_TO_POINTER (each_key->data));
+ }
+ g_list_free (related_keys);
+ }
+ g_hash_table_unref (registry->priv->related_keys);
+ registry->priv->related_keys = NULL;
+ }
+
+ g_slist_free_full (registry->priv->plugins_dir, (GDestroyNotify) g_free);
+ g_slist_free_full (registry->priv->allowed_plugins, (GDestroyNotify) g_free);
+
+ key_id_handler_free (®istry->priv->key_id_handler);
+
+ G_OBJECT_CLASS (grl_registry_parent_class)->finalize (object);
+}
+
/* ================ Utitilies ================ */
static void
@@ -513,6 +589,13 @@ key_id_handler_init (struct KeyIDHandler *handler)
null_string);
}
+static void
+key_id_handler_free (struct KeyIDHandler *handler)
+{
+ g_hash_table_unref (handler->string_to_id);
+ g_array_unref (handler->id_to_string);
+}
+
static
GrlKeyID key_id_handler_get_key (struct KeyIDHandler *handler, const gchar *key_name)
{
@@ -589,6 +672,18 @@ key_id_handler_get_all_keys (struct KeyIDHandler *handler)
return g_hash_table_get_values (handler->string_to_id);
}
+static void
+shutdown_plugin (GrlPlugin *plugin)
+{
+ GRL_DEBUG ("Unloading plugin '%s'", grl_plugin_get_id (plugin));
+ grl_plugin_unload (plugin);
+
+ if (grl_plugin_get_module (plugin)) {
+ g_module_close (grl_plugin_get_module (plugin));
+ grl_plugin_set_module (plugin, NULL);
+ }
+}
+
/* ================ PRIVATE API ================ */
/*
@@ -644,6 +739,7 @@ grl_registry_get_default (void)
if (!registry) {
registry = g_object_new (GRL_TYPE_REGISTRY, NULL);
+ g_object_add_weak_pointer (G_OBJECT (registry), (gpointer *) ®istry);
}
return registry;
@@ -1227,13 +1323,7 @@ grl_registry_unload_plugin (GrlRegistry *registry,
g_list_free (sources);
/* Third, shut down the plugin */
- GRL_DEBUG ("Unloading plugin '%s'", plugin_id);
- grl_plugin_unload (plugin);
-
- if (grl_plugin_get_module (plugin)) {
- g_module_close (grl_plugin_get_module (plugin));
- grl_plugin_set_module (plugin, NULL);
- }
+ shutdown_plugin (plugin);
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]