[evolution] EModule: Make all modules resident.



commit f70f196d4d993d3337545567896f69449cdb6271
Author: Matthew Barnes <mbarnes redhat com>
Date:   Fri Aug 5 08:41:27 2011 -0500

    EModule: Make all modules resident.
    
    Works around a design flaw in EExtension.
    
    See the comment in e-module.c for more details.

 e-util/e-extensible.c |   24 +++++++++++-------------
 e-util/e-module.c     |   19 +++++++++++++++++++
 2 files changed, 30 insertions(+), 13 deletions(-)
---
diff --git a/e-util/e-extensible.c b/e-util/e-extensible.c
index 6e49e9d..a7523de 100644
--- a/e-util/e-extensible.c
+++ b/e-util/e-extensible.c
@@ -94,19 +94,17 @@ extensible_load_extension (GType extension_type,
 	extension_class = g_type_class_ref (extension_type);
 
 	/* Only load extensions that extend the given extensible object. */
-	if (g_type_is_a (extensible_type, extension_class->extensible_type)) {
-		extension = g_object_new (
-			extension_type, "extensible", extensible, NULL);
-
-		extensions = extensible_get_extensions (extensible);
-		g_ptr_array_add (extensions, extension);
-
-		g_type_class_unref (extension_class);
-	} else {
-		/* keep the class referenced forever, later may anyone need it anyway,
-		   and unref it may mean module unload, which breaks static strings
-		   in GType */
-	}
+	if (!g_type_is_a (extensible_type, extension_class->extensible_type))
+		goto exit;
+
+	extension = g_object_new (
+		extension_type, "extensible", extensible, NULL);
+
+	extensions = extensible_get_extensions (extensible);
+	g_ptr_array_add (extensions, extension);
+
+exit:
+	g_type_class_unref (extension_class);
 }
 
 static void
diff --git a/e-util/e-module.c b/e-util/e-module.c
index b3e90aa..4648608 100644
--- a/e-util/e-module.c
+++ b/e-util/e-module.c
@@ -139,6 +139,25 @@ module_load (GTypeModule *type_module)
 
 	priv->load (type_module);
 
+	/* XXX This is a Band-Aid for a design flaw in EExtension.  If the
+	 *     "extensible_type" member of EExtensionClass is set to a GType
+	 *     that hasn't already been registered, then when the extension's
+	 *     module is unloaded the GType registration that was triggered
+	 *     by setting "extensible_type" will be invalidated and cause
+	 *     Evolution to malfunction when the module is loaded again.
+	 *
+	 *     Extension modules get loaded and unloaded repeatedly by
+	 *     e_extensible_load_extensions(), which temporarily references
+	 *     all extension classes and picks out the ones it needs for a
+	 *     given EExtensible instance based on the "extensible_type"
+	 *     class member.
+	 *
+	 *     Making the module resident prevents the aforementioned GType
+	 *     registration from being invalidated when the extension class
+	 *     is unreferenced.
+	 */
+	g_module_make_resident (priv->module);
+
 	return TRUE;
 
 fail:



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]