diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-07-23 18:57:49 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-07-23 19:01:46 (GMT) |
commit | abefe01dd260cddbd253ba0c03d9c903138c71c1 (patch) | |
tree | 834f683e79893534324af94c537984542b7dc00a /src/plugins/pglist.c | |
parent | 50eb8c462e7ad2b4e5b82d27b1af6e86091ea272 (diff) |
Tracked the reference counter for plugins with more care.
Diffstat (limited to 'src/plugins/pglist.c')
-rw-r--r-- | src/plugins/pglist.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c index 1f608b4..57f7538 100644 --- a/src/plugins/pglist.c +++ b/src/plugins/pglist.c @@ -54,6 +54,9 @@ static int filter_dirs_or_mods(const struct dirent *); /* Part à la recherche de greffons sous forme de modules. */ static void browse_directory_for_plugins(const char *); +/* Suivit les variations du compteur de références d'un greffon. */ +static void on_plugin_ref_toggle(gpointer, GPluginModule *, gboolean); + /****************************************************************************** @@ -97,16 +100,55 @@ bool init_all_plugins(bool load) void exit_all_plugins(void) { 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++) + { + 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; + g_object_unref(_pg_list[i]); + } + free(_pg_list); } + unlock_plugin_list_for_reading(); + g_rw_lock_clear(&_pg_lock); } @@ -269,6 +311,48 @@ void _register_plugin(GPluginModule *plugin) _pg_list[_pg_count - 1] = plugin; + g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : unused = adresse non utilisée ici. * +* plugin = greffon àà venir effacer de la liste au besoin. * +* last = indication sur la valeur du compteur de références. * +* * +* Description : Suivit les variations du compteur de références d'un greffon.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolean last) +{ + const plugin_interface *pg_iface; /* Vitrine d'un greffon */ + size_t index; /* Indice du greffon */ + GPluginModule *same; /* Juste pour la récupération */ + + if (last) + { + assert(g_rw_lock_writer_trylock(&_pg_lock) == FALSE); + + pg_iface = g_plugin_module_get_interface(plugin); + + same = get_plugin_by_name(pg_iface->name, &index); + assert(same != NULL); + + _pg_list[index] = NULL; + + g_object_remove_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL); + + g_object_unref(G_OBJECT(same)); + } } @@ -406,6 +490,9 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index) for (i = 0; i < _pg_count && result == NULL; i++) { + /* Si on est en train de procéder à un nettoyage... */ + if (_pg_list[i] == NULL) continue; + pg_iface = g_plugin_module_get_interface(_pg_list[i]); if (strcmp(pg_iface->name, name) == 0) |