diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/native-int.h | 13 | ||||
-rw-r--r-- | src/plugins/native.c | 29 | ||||
-rw-r--r-- | src/plugins/native.h | 7 | ||||
-rw-r--r-- | src/plugins/pglist.c | 144 | ||||
-rw-r--r-- | src/plugins/plugin.c | 12 |
5 files changed, 132 insertions, 73 deletions
diff --git a/src/plugins/native-int.h b/src/plugins/native-int.h index 8b8e0eb..575994f 100644 --- a/src/plugins/native-int.h +++ b/src/plugins/native-int.h @@ -41,7 +41,18 @@ struct _GNativePlugin { GPluginModule parent; /* A laisser en premier */ - GModule *module; /* Abstration de manipulation */ + /** + * Le module porte le code et les données en mémoire. + * + * Les fonctions *_dispose() et *_finalize() accompagnant la libération des + * greffons de la mémoire ne peuvent donc pas libérer ce module car elles + * scieraient la branche sur laquelle elles se trouvent. + * + * Par ailleurs, même s'ils sont conservés dans chaque greffon, les modules + * sont mis en place dans le code principal. C'est donc ce dernier qui les + * libère, dans la fonction on_plugin_ref_toggle(). + */ + GModule *module; /* Structure de chargement GLib*/ }; diff --git a/src/plugins/native.c b/src/plugins/native.c index fedccbe..de20abe 100644 --- a/src/plugins/native.c +++ b/src/plugins/native.c @@ -131,12 +131,6 @@ static void g_native_plugin_init(GNativePlugin *plugin) static void g_native_plugin_dispose(GNativePlugin *plugin) { - if (plugin->module != NULL) - { - g_module_close(plugin->module); - plugin->module = NULL; - } - G_OBJECT_CLASS(g_native_plugin_parent_class)->dispose(G_OBJECT(plugin)); } @@ -194,6 +188,29 @@ bool g_native_plugin_create(GNativePlugin *plugin, const char *name, const char } +/****************************************************************************** +* * +* Paramètres : plugin = greffon à consulter. * +* * +* Description : Renvoie la structure opaque associée au module en mémoire. * +* * +* Retour : Structure de chargement côté GLib. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GModule *g_native_plugin_get_module(const GNativePlugin *plugin) +{ + GModule *result; /* Accès au module à renvoyer */ + + result = plugin->module; + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ diff --git a/src/plugins/native.h b/src/plugins/native.h index 205342c..18039c8 100644 --- a/src/plugins/native.h +++ b/src/plugins/native.h @@ -26,6 +26,9 @@ #define _PLUGINS_NATIVE_H +#include <gmodule.h> + + #include "../glibext/helpers.h" @@ -35,5 +38,9 @@ DECLARE_GTYPE(GNativePlugin, g_native_plugin, G, NATIVE_PLUGIN); +/* Renvoie la structure opaque associée au module en mémoire. */ +GModule *g_native_plugin_get_module(const GNativePlugin *); + + #endif /* _PLUGINS_NATIVE_H */ diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c index 277e4f5..6dc2d9c 100644 --- a/src/plugins/pglist.c +++ b/src/plugins/pglist.c @@ -37,9 +37,10 @@ #include "manager.h" +#include "native.h" #include "plugin-int.h" #include "../common/cpp.h" -#include "../common/extstr.h" // REMME ? +#include "../common/extstr.h" #include "../core/logs.h" #include "../core/nox.h" #include "../core/paths.h" @@ -69,6 +70,9 @@ static void browse_directory_for_plugins(const char *); /* Suit les variations du compteur de références d'un greffon. */ static void on_plugin_ref_toggle(gpointer, GPluginModule *, gboolean); +/* Fournit le greffon répondant à un nom donné. */ +static GPluginModule *_find_plugin_by_name(const char *, size_t *); + /****************************************************************************** @@ -134,71 +138,23 @@ bool init_all_plugins(bool load) void exit_all_plugins(void) { - -#if 0 ////// - - size_t i; /* Boucle de parcours */ - const plugin_interface *pg_iface; /* Définition du greffon */ lock_plugin_list_for_reading(); - if (_pg_list != NULL) + for (i = 0; i < _pg_count; i++) { - for (i = 0; i < _pg_count; i++) - { - assert(_pg_list[i] != NULL); - - /** - * Si le greffon a conduit à la mise en place d'autres greffons, le - * système de dépendances ne suffit pas pour le décompte des références : - * le greffon voit à un instant T son compteur décroître ici ; à un - * instant T+1, un greffon fils décrémente à son tour le compteur vers - * le greffon principal. - * - * Le compteur du conteneur tombe alors à 0, et le code correspondant - * est retiré. Lorsque que le flot d'exécution revient à la procédure - * de sortie du second greffon, son code n'est plus en mémoire. - * - * On s'assure donc que les greffons qui génèrent d'autres greffons - * sont bien traités en dernier. - */ - - pg_iface = g_plugin_module_get_interface(_pg_list[i]); - - if (pg_iface != NULL && pg_iface->container) - g_object_ref(_pg_list[i]); - - g_object_unref(_pg_list[i]); - - } - - for (i = 0; i < _pg_count; i++) - { - if (_pg_list[i] == NULL) - continue; - - pg_iface = g_plugin_module_get_interface(_pg_list[i]); - - if (pg_iface == NULL || !pg_iface->container) - continue; - - g_object_unref(_pg_list[i]); - - } + assert(_pg_list[i] != NULL); + unref_object(_pg_list[i]); + } + if (_pg_list != NULL) free(_pg_list); - } - unlock_plugin_list_for_reading(); g_rw_lock_clear(&_pg_lock); - - -#endif - } @@ -485,6 +441,7 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea const char *name; /* Désignation du greffon */ size_t index; /* Indice du greffon */ GPluginModule *same; /* Juste pour la récupération */ + GModule *module; /* Structure de chargement GLib*/ if (last) { @@ -492,15 +449,44 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea name = g_plugin_module_get_name(plugin); - same = get_plugin_by_name(name, &index); + /** + * Les mécanismes de g_object_unref() prennent en compte la bascule d'un + * compteur de références initialement à 2 avant appel pour déclencher + * cet appel à on_plugin_ref_toggle() mis en place par g_object_add_toggle_ref(). + * + * Incrémenter ce compteur à nouveau, via get_plugin_by_name(), puis le + * décrémenter ensuite via unref_object() va conduire à une nouvelle + * bascule des statuts de suivi dans g_object_unref(). + * + * Il est ainsi impératif de rechercher une instance du greffon dans + * la liste des extensions sans toucher au compteur de références. + */ + + same = _find_plugin_by_name(name, &index); + assert(same != NULL); assert(same == plugin); - g_clear_object(&_pg_list[index]); + _pg_list[index] = NULL; + + /** + * Suppression de la dernière référence. + */ + + if (G_IS_NATIVE_PLUGIN(plugin)) + module = g_native_plugin_get_module(G_NATIVE_PLUGIN(plugin)); + else + module = NULL; g_object_remove_toggle_ref(G_OBJECT(same), (GToggleNotify)on_plugin_ref_toggle, NULL); - unref_object(same); + /** + * Plus aucun code issu du greffon n'est désormais utile. Le module associé peut + * être libéré de la mémoire. + */ + + if (module != NULL) + g_module_close(module); } @@ -622,13 +608,18 @@ void load_remaning_plugins(void) /* Supprime les greffons non chargés */ - for (i = 0; i < _pg_count; i++) + for (i = 0; i < _pg_count;) { flags = g_plugin_module_get_flags(_pg_list[i]); - if ((flags & PSF_LOADED) == 0) + if (flags & PSF_LOADED) + i++; + + else { - g_object_unref(G_OBJECT(_pg_list[i])); + unref_object(_pg_list[i]); + + assert(_pg_list[i] == NULL); memmove(&_pg_list[i], &_pg_list[i + 1], (_pg_count - i - 1) * sizeof(GPluginModule *)); _pg_count--; @@ -655,11 +646,12 @@ void load_remaning_plugins(void) * * * Retour : Instance du greffon trouvé ou NULL si aucun. * * * -* Remarques : - * +* Remarques : Le compteur de référence d'un greffon trouvé n'est pas * +* modifié. * * * ******************************************************************************/ -GPluginModule *get_plugin_by_name(const char *name, size_t *index) +static GPluginModule *_find_plugin_by_name(const char *name, size_t *index) { GPluginModule *result; /* Greffon trouvé à renvoyer */ size_t i; /* Boucle de parcours */ @@ -682,7 +674,6 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index) if (strcmp(current, name) == 0) { result = _pg_list[i]; - ref_object(result); if (index != NULL) *index = i; @@ -698,6 +689,33 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index) /****************************************************************************** * * +* Paramètres : name = désignation du greffon recherché. * +* index = indice du greffon trouvé. [OUT] * +* * +* Description : Fournit le greffon répondant à un nom donné. * +* * +* Retour : Instance du greffon trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GPluginModule *get_plugin_by_name(const char *name, size_t *index) +{ + GPluginModule *result; /* Greffon trouvé à renvoyer */ + + result = _find_plugin_by_name(name, index); + + if (result != NULL) + ref_object(result); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : count = nombre de greffons trouvés. [OUT] * * * * Description : Fournit la liste de l'ensemble des greffons. * diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index d14e656..9438f9f 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -159,10 +159,14 @@ static void g_plugin_module_dispose(GPluginModule *plugin) unlock_plugin_list_for_reading(); - class = G_PLUGIN_MODULE_GET_CLASS(plugin); + if (plugin->flags & PSF_LOADED) + { + class = G_PLUGIN_MODULE_GET_CLASS(plugin); - if (class->disable != NULL) - class->disable(plugin); + if (class->disable != NULL) + class->disable(plugin); + + } G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin)); @@ -185,6 +189,8 @@ static void g_plugin_module_finalize(GPluginModule *plugin) { size_t i; /* Boucle de parcours */ + printf("[!!!] Finalizing plugin %s\n", plugin->name); + if (plugin->name != NULL) free(plugin->name); |