summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2021-01-03 15:12:38 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2021-01-03 15:12:38 (GMT)
commite790ebee8ad78e91fc61738c5c40062ed36b1d44 (patch)
treeec9cbd3f383038ebf35a11037a170150dcfacaf3 /plugins
parentdcd5e0b104143b110997029aa0728731f4087ad8 (diff)
Fixed a memory leak when a Python plugin fails to load.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/pychrysalide/core.c31
-rw-r--r--plugins/pychrysalide/plugin.c33
2 files changed, 43 insertions, 21 deletions
diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c
index a148654..7bc46e4 100644
--- a/plugins/pychrysalide/core.c
+++ b/plugins/pychrysalide/core.c
@@ -664,6 +664,7 @@ static void load_python_plugins(GPluginModule *plugin)
struct dirent *entry; /* Elément trouvé */
char *modname; /* Nom du module pour Python */
char *filename; /* Chemin d'accès reconstruit */
+ PyThreadState *tstate; /* Contexte d'environnement */
GPluginModule *pyplugin; /* Lien vers un grffon Python */
bool status; /* Bilan d'une opération */
GGenConfig *config; /* Configuration à charger */
@@ -743,8 +744,17 @@ static void load_python_plugins(GPluginModule *plugin)
filename = stradd(filename, G_DIR_SEPARATOR_S);
filename = stradd(filename, entry->d_name);
+ if (!_standalone)
+ {
+ tstate = get_pychrysalide_main_tstate();
+ PyEval_RestoreThread(tstate);
+ }
+
pyplugin = g_python_plugin_new(modname, filename);
+ if (!_standalone)
+ PyEval_SaveThread();
+
if (pyplugin == NULL)
{
g_plugin_module_log_variadic_message(plugin, LMT_ERROR,
@@ -761,6 +771,7 @@ static void load_python_plugins(GPluginModule *plugin)
{
g_plugin_module_log_variadic_message(plugin, LMT_ERROR,
_("Plugin '%s' failed to complete loading..."), filename);
+ g_object_unref(G_OBJECT(pyplugin));
goto done_with_plugin;
}
@@ -772,12 +783,6 @@ static void load_python_plugins(GPluginModule *plugin)
_("Loaded the Python plugin found in the '<b>%s</b>' directory"),
filename);
- /**
- * Comme le greffon n'est pas passé par la résolution des dépendances,
- * on simule l'effet attendu.
- */
- g_object_ref(G_OBJECT(plugin));
-
_register_plugin(pyplugin);
done_with_plugin:
@@ -894,23 +899,9 @@ G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin)
G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin, PluginAction action)
{
- PyThreadState *tstate; /* Contexte d'environnement */
-
if (action == PGA_NATIVE_PLUGINS_LOADED)
- {
- if (!_standalone)
- {
- tstate = get_pychrysalide_main_tstate();
- PyEval_RestoreThread(tstate);
- }
-
load_python_plugins(plugin);
- if (!_standalone)
- PyEval_SaveThread();
-
- }
-
}
diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c
index aa91fb8..88b20de 100644
--- a/plugins/pychrysalide/plugin.c
+++ b/plugins/pychrysalide/plugin.c
@@ -34,6 +34,7 @@
#include <common/extstr.h>
#include <plugins/dt.h>
+#include <plugins/pglist.h>
#include <plugins/self.h>
@@ -274,6 +275,7 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)
int ret; /* Bilan d'un appel */
GPluginModule *plugin; /* Greffon à manipuler */
plugin_interface *iface; /* Interface à constituer */
+ GPluginModule *dependency; /* Module nécessaire */
PyObject *value; /* Valeur à présence imposée */
size_t i; /* Boucle de parcours */
PyObject *action; /* Identifiant d'une action */
@@ -353,10 +355,37 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)
iface->container = false;
+ /**
+ * Comme le greffon n'est pas passé par la résolution des dépendances,
+ * orchestrée par la fonction g_plugin_module_resolve_dependencies(),
+ * on simule l'effet attendu en obtenant une référence par un appel à
+ * get_plugin_by_name().
+ *
+ * L'incrémentation des références doit coller au plus près de
+ * l'inscription nominative du greffon : en cas de sortie impromptue
+ * (lorsqu'une erreur intervient pendant un chargement par exemple),
+ * l'état de l'ensemble est ainsi cohérent au moment du retrait du
+ * greffon fautif via la fonction g_plugin_module_dispose().
+ */
+
+ lock_plugin_list_for_reading();
+ dependency = get_plugin_by_name("PyChrysalide", NULL);
+ unlock_plugin_list_for_reading();
+
+ assert(dependency != NULL);
+
+ if (dependency == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, _("The internal name of the Python plugin has changed!"));
+ return -1;
+ }
+
iface->required = malloc(sizeof(char *));
iface->required[0] = "PyChrysalide";
iface->required_count = 1;
+ /* Validation du reste de l'interface */
+
value = PyObject_GetAttrString(self, "_actions");
if (value == NULL)
@@ -1331,6 +1360,7 @@ static void g_python_plugin_init(GPythonPlugin *plugin)
static void g_python_plugin_dispose(GPythonPlugin *plugin)
{
+#if 0
PyThreadState *tstate; /* Contexte d'environnement */
/**
@@ -1361,6 +1391,7 @@ static void g_python_plugin_dispose(GPythonPlugin *plugin)
if (tstate != NULL)
PyEval_SaveThread();
+#endif
G_OBJECT_CLASS(g_python_plugin_parent_class)->dispose(G_OBJECT(plugin));
@@ -1392,7 +1423,7 @@ static void g_python_plugin_finalize(GPythonPlugin *plugin)
if (final->version != NULL) free(final->version);
if (final->url != NULL) free(final->url);
- assert(final->required_count <= 1);
+ assert(final->required_count == 1);
if (final->required != NULL)
free(final->required);