summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/pe/core.c15
-rw-r--r--plugins/pychrysalide/bindings.c125
-rw-r--r--plugins/pychrysalide/bindings.h14
-rw-r--r--plugins/pychrysalide/core-ui.c3
-rw-r--r--plugins/pychrysalide/core.c42
-rw-r--r--src/core/core.h8
-rw-r--r--src/plugins/native-int.h13
-rw-r--r--src/plugins/native.c29
-rw-r--r--src/plugins/native.h7
-rw-r--r--src/plugins/pglist.c144
-rw-r--r--src/plugins/plugin.c12
11 files changed, 240 insertions, 172 deletions
diff --git a/plugins/pe/core.c b/plugins/pe/core.c
index 42f712d..9d30a34 100644
--- a/plugins/pe/core.c
+++ b/plugins/pe/core.c
@@ -62,8 +62,8 @@ static void g_pe_plugin_finalize(GPePlugin *);
/* Prend acte de l'activation du greffon. */
static bool g_pe_plugin_enable(GPePlugin *);
-/* Prend acte de l'extinction du greffon. */
-static void g_pe_plugin_disable(GPePlugin *);
+/* Prend acte de la désactivation du greffon. */
+static bool g_pe_plugin_disable(GPePlugin *);
@@ -288,16 +288,21 @@ static bool g_pe_plugin_enable(GPePlugin *plugin)
* *
* Paramètres : plugin = greffon à manipuler. *
* *
-* Description : Prend acte de l'extinction du greffon. *
+* Description : Prend acte de la désactivation du greffon. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_pe_plugin_disable(GPePlugin *plugin)
+static bool g_pe_plugin_disable(GPePlugin *plugin)
{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ return result;
}
diff --git a/plugins/pychrysalide/bindings.c b/plugins/pychrysalide/bindings.c
index 02850d1..99491d6 100644
--- a/plugins/pychrysalide/bindings.c
+++ b/plugins/pychrysalide/bindings.c
@@ -25,16 +25,15 @@
#include "bindings.h"
-#ifdef PYTHON_PACKAGE
-# include <dlfcn.h>
-#endif
+#include <assert.h>
+#include <dlfcn.h>
#include <pygobject.h>
#include <stdio.h>
-#include <config.h>
#include <common/cpp.h>
#include <common/extstr.h>
+#include <core/core.h>
#include <plugins/pglist.h>
#include <plugins/self.h>
@@ -125,6 +124,8 @@ static void restore_original_pygobject_type(PyTypeObject *);
/* ------------------------ FONCTIONS GLOBALES DE CHRYSALIDE ------------------------ */
+/* Assure le plein chargement dans un interpréteur Python. */
+static bool init_python_interpreter_for_standalone_mode(const pyinit_details_t *);
/* Point de sortie pour l'initialisation de Python. */
static void PyExit_pychrysalide(void);
@@ -915,7 +916,7 @@ PyObject *init_python_pychrysalide_module(const pyinit_details_t *details)
PyErr_SetString(PyExc_SystemError, "failed to load all PyChrysalide components.");
else if (details->standalone)
- status = do_global_init();
+ status = init_python_interpreter_for_standalone_mode(details);
if (!status)
{
@@ -1060,13 +1061,11 @@ void log_pychrysalide_exception(const char *prefix, ...)
/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : py_gobj_def = définition de type actuelle. [OUT] *
+* Paramètres : details = précisions de chargement complémentaires. *
* *
-* Description : Restore une ancienne définition de type GObject au besoin. *
+* Description : Assure le plein chargement dans un interpréteur Python. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -1074,103 +1073,77 @@ void log_pychrysalide_exception(const char *prefix, ...)
* *
******************************************************************************/
-bool do_global_init(void)
+static bool init_python_interpreter_for_standalone_mode(const pyinit_details_t *details)
{
-
- return true;
- return false;
-
-
-#if 0
-
-
bool result; /* Bilan à retourner */
int ret; /* Bilan de préparatifs */
-#ifdef PYTHON_PACKAGE
Dl_info info; /* Informations dynamiques */
-#endif
+ GModule *module; /* Structure de chargement GLib*/
GPluginModule *self; /* Représentation interne */
- PluginStatusFlags self_flags; /* Fanions à mettre à jour */
+
+ result = false;
ret = Py_AtExit(PyExit_pychrysalide);
if (ret == -1)
{
PyErr_SetString(PyExc_SystemError, "failed to register a cleanup function.");
- goto exit_and_restore;
+ goto exit;
+ }
+
+ if (!load_core_components(ACC_ALL_COMPONENTS))
+ {
+ PyErr_SetString(PyExc_SystemError, "unable to load core components.");
+ goto exit;
}
/**
- * Si cette extension pour Python est chargée depuis un dépôt Python,
- * elle ne se trouve pas dans le répertoire classique des extensions et
- * n'est donc pas chargée et enregistrée comme attendu.
+ * Le module chargé par Python n'apparaît pas dans la liste des greffons de
+ * Chrysalide et ne peut donc pas être référencé comme dépendance par d'autres
+ * extensions.
*
- * Cet enregistrement est donc forcé ici.
+ * Par ailleurs, lors de la recherche d'autres greffons via l'appel à la
+ * fonction init_all_plugins() ci-après, il faut que le nom du greffon soit
+ * déjà réservé pour faire échouer le second chargement du greffon courant
+ * lors du parcours des répertoires conservant les fichiers d'extensions.
*/
-#ifdef PYTHON_PACKAGE
-
ret = dladdr(__FUNCTION__, &info);
if (ret == 0)
{
LOG_ERROR_DL_N("dladdr");
-
- // err msg
-
-
- Py_DECREF(result);
- result = NULL;
-
- goto exit_and_restore;
- }
-
- self = g_plugin_module_new(info.dli_fname);
- assert(self != NULL);
-
- register_plugin(self);
-
-#endif
-
-
- if (!load_core_components(ACC_GLOBAL_VARS))
- {
- PyErr_SetString(PyExc_SystemError, "unable to load core components.");
+ PyErr_SetString(PyExc_SystemError, "failed to force bindings registration.");
goto exit;
- }
- init_all_plugins(false);
+ }
- lock_plugin_list_for_reading();
+ module = g_module_open(info.dli_fname, G_MODULE_BIND_LAZY);
+ assert(module != NULL);
- self = get_plugin_by_name("PyChrysalide", NULL);
- assert(self != NULL);
+ self = details->create_self(module);
- self_flags = g_plugin_module_get_flags(self);
- self_flags &= ~(PSF_FAILURE | PSF_LOADED);
- self_flags |= (status ? PSF_LOADED : PSF_FAILURE);
+ /* A ce stade, le greffon a été chargé correctement */
+ g_plugin_module_override_flags(self, PSF_LOADED);
- g_plugin_module_override_flags(self, self_flags);
+ register_plugin(self);
unref_object(self);
- unlock_plugin_list_for_reading();
-
- load_remaning_plugins();
-
-
+ /**
+ * Intégration des fonctionnalités portées par d'autres greffons.
+ */
+ result = true;
+ init_all_plugins(true);
- done:
+ exit:
return result;
-#endif
-
}
-
/******************************************************************************
* *
* Paramètres : - *
@@ -1185,24 +1158,8 @@ bool do_global_init(void)
static void PyExit_pychrysalide(void)
{
- //assert(_standalone);
-
- /*
- extern void set_current_project(void *project);
-
- set_current_project(NULL);
- */
-
-#ifdef TRACK_GOBJECT_LEAKS
- remember_gtypes_for_leaks();
-#endif
-
exit_all_plugins();
- //unload_all_core_components(true);
-
-#ifdef TRACK_GOBJECT_LEAKS
- dump_remaining_gtypes();
-#endif
+ unload_core_components(ACC_ALL_COMPONENTS);
}
diff --git a/plugins/pychrysalide/bindings.h b/plugins/pychrysalide/bindings.h
index e9ee421..1758747 100644
--- a/plugins/pychrysalide/bindings.h
+++ b/plugins/pychrysalide/bindings.h
@@ -36,9 +36,13 @@
#include <Python.h>
+#include <gmodule.h>
#include <stdbool.h>
+#include <plugins/plugin.h>
+
+
/* Charge un module GI dans Python avec une version attendue. */
bool import_namespace_from_gi_repository(const char *, const char *);
@@ -50,6 +54,12 @@ typedef struct _pyinit_details_t
bool (* populate_extra) (void); /* Ajout de types ? */
+ /**
+ * Prototype de la fonction de création, à garder synchronisé avec
+ * NATIVE_PLUGIN_ENTRYPOINT() (cf. native-int.h).
+ */
+ GPluginModule * (* create_self) (GModule *);
+
} pyinit_details_t;
/* Implémente le point d'entrée pour l'initialisation de Python. */
@@ -60,8 +70,4 @@ void log_pychrysalide_exception(const char *, ...);
-bool do_global_init(void);
-
-
-
#endif /* _PLUGINS_PYCHRYSALIDE_BINDINGS_H */
diff --git a/plugins/pychrysalide/core-ui.c b/plugins/pychrysalide/core-ui.c
index 32d3516..1b332b7 100644
--- a/plugins/pychrysalide/core-ui.c
+++ b/plugins/pychrysalide/core-ui.c
@@ -179,7 +179,7 @@ GPluginModule *g_pychrysalide_plugin_ui_new(GModule *module)
{
GPyChrysalidePluginUI *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_PYCHRYSALIDE_PLUGIN, NULL);
+ result = g_object_new(G_TYPE_PYCHRYSALIDE_PLUGIN_UI, NULL);
if (!g_pychrysalide_plugin_ui_create(result, module))
g_clear_object(&result);
@@ -310,6 +310,7 @@ PyMODINIT_FUNC PyInit_pychrysalideui(void)
details.standalone = _standalone;
details.populate_extra = NULL;
+ details.create_self = g_pychrysalide_plugin_ui_new;
result = init_python_pychrysalide_module(&details);
diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c
index fde1028..0e72b46 100644
--- a/plugins/pychrysalide/core.c
+++ b/plugins/pychrysalide/core.c
@@ -390,16 +390,53 @@ static bool g_pychrysalide_plugin_enable(GPyChrysalidePlugin *plugin)
static bool g_pychrysalide_plugin_disable(GPyChrysalidePlugin *plugin)
{
+ bool result; /* Bilan à retourner */
+ bool standalone; /* Nature du chargement */
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
- gstate = PyGILState_Ensure();
+ result = true;
+
+ /**
+ * Le champ plugin->py_module n'est défini que via la fonction
+ * g_pychrysalide_plugin_enable(), qui n'est pas sollicitée lorsque
+ * le module PyChrysalide est mis en place directement par Python.
+ *
+ * L'analyse de ce champ pour retrouver la situation courante est
+ * plus fiable que celle du champ _standalone, potentiellement
+ * cohérent dans la version UI du greffon et resté à son état
+ * initial ici.
+ */
+
+ standalone = (plugin->py_module == NULL);
+
+ /**
+ * Si on se trouve embarqué dans un interpréteur Python, le déchargement
+ * des greffons est organisé à partir de la fonction PyExit_pychrysalide(),
+ * directement appelée depuis un contexte Python.
+ *
+ * Un verrou n'est alors pas souhaité ici :
+ *
+ * python3d: ../Python/pystate.c:1687: PyGILState_Ensure: Assertion `gilstate->autoInterpreterState' failed.
+ *
+ * Avec :
+ *
+ * $ python3d --version
+ * Python 3.11.2
+ *
+ */
+
+ if (!standalone)
+ gstate = PyGILState_Ensure();
clear_all_accesses_to_python_modules();
Py_XDECREF(plugin->py_module);
plugin->py_module = NULL;
- PyGILState_Release(gstate);
+ if (!standalone)
+ PyGILState_Release(gstate);
+
+ return result;
}
@@ -720,6 +757,7 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
details.standalone = _standalone;
details.populate_extra = NULL;
+ details.create_self = g_pychrysalide_plugin_new;
result = init_python_pychrysalide_module(&details);
diff --git a/src/core/core.h b/src/core/core.h
index 7c50f6c..e5f0a60 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -32,9 +32,11 @@
/* Eléments à (dé)charger disponibles */
typedef enum _AvailableCoreComponent
{
- ACC_NONE = (0 << 0), /* Statut initial */
- ACC_GLOBAL_VARS = (1 << 0), /* Singletons globaux */
- ACC_SCAN_FEATURES = (1 << 0), /* Espace de noms pour scan */
+ ACC_NONE = (0 << 0), /* Statut initial */
+ ACC_GLOBAL_VARS = (1 << 0), /* Singletons globaux */
+ ACC_SCAN_FEATURES = (1 << 1), /* Espace de noms pour scan */
+
+ ACC_ALL_COMPONENTS = (1 << 2) - 1
} AvailableCoreComponent;
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);