summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2025-01-13 07:34:49 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2025-01-13 07:34:49 (GMT)
commit59ab0336eaab192ca2f02b67d143a1ba4d1aac2b (patch)
tree824215b03d19bd8a188cc480b376d2ff882773eb /plugins
parent71367e25e95b90b34891ec88083a52e0e0f60f13 (diff)
Handle load errors due to buggy Python plugins.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/pychrysalide/bindings.c120
-rw-r--r--plugins/pychrysalide/bindings.h5
-rw-r--r--plugins/pychrysalide/core.c148
3 files changed, 123 insertions, 150 deletions
diff --git a/plugins/pychrysalide/bindings.c b/plugins/pychrysalide/bindings.c
index 295667f..f715a8e 100644
--- a/plugins/pychrysalide/bindings.c
+++ b/plugins/pychrysalide/bindings.c
@@ -34,6 +34,7 @@
#include <config.h>
#include <common/cpp.h>
+#include <common/extstr.h>
#include <plugins/pglist.h> // REMME ?
#include <plugins/self.h> // REMME ?
@@ -929,13 +930,130 @@ PyObject *init_python_pychrysalide_module(const pyinit_details_t *details)
exit:
if (result == NULL && !details->standalone)
- /*log_pychrysalide_exception("Loading failed")*/;
+ log_pychrysalide_exception("Python bindings loading failed");
return result;
}
+/******************************************************************************
+* *
+* Paramètres : prefix = message d'introduction à faire apparaître à l'écran.*
+* *
+* Description : Présente dans le journal une exception survenue. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void log_pychrysalide_exception(const char *prefix, ...)
+{
+ va_list ap; /* Compléments argumentaires */
+ char *msg; /* Message complet à imprimer */
+ PyObject *err_type; /* Type d'erreur Python */
+ PyObject *err_value; /* Instance Python d'erreur */
+ PyObject *err_traceback; /* Trace Python associée */
+ PyObject *err_string; /* Description Python d'erreur */
+ const char *err_msg; /* Représentation humaine */
+
+ assert(PyGILState_Check() == 1);
+
+ if (PyErr_Occurred())
+ {
+ /* Base de la communication */
+
+ va_start(ap, prefix);
+
+ vasprintf(&msg, prefix, ap);
+
+ va_end(ap);
+
+ /* Détails complémentaires */
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+
+ if (err_traceback == NULL)
+ {
+ err_traceback = Py_None;
+ Py_INCREF(err_traceback);
+ }
+
+ PyException_SetTraceback(err_value, err_traceback);
+
+ if (err_value == NULL)
+ msg = stradd(msg, _(": no extra information is provided..."));
+
+ else
+ {
+ err_string = PyObject_Str(err_value);
+ err_msg = PyUnicode_AsUTF8(err_string);
+
+ msg = stradd(msg, ": ");
+ msg = stradd(msg, err_msg);
+
+ Py_DECREF(err_string);
+
+ }
+
+ /**
+ * Bien que la documentation précise que la fonction PyErr_Fetch()
+ * transfère la propritété des éléments retournés, la pratique
+ * montre que le programme plante à la terminaison en cas d'exception.
+ *
+ * C'est par exemple le cas quand un greffon Python ne peut se lancer
+ * correctement ; l'exception est alors levée à partir de la fonction
+ * create_python_plugin() et le plantage intervient en sortie d'exécution,
+ * au moment de la libération de l'extension Python :
+ *
+ * ==14939== Jump to the invalid address stated on the next line
+ * ==14939== at 0x1A8FCBC9: ???
+ * ==14939== by 0x53DCDB2: g_object_unref (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5800.3)
+ * ==14939== by 0x610F834: on_plugin_ref_toggle (pglist.c:370)
+ * ==14939== by 0x610F31A: exit_all_plugins (pglist.c:153)
+ * ==14939== by 0x10AD19: main (main.c:440)
+ * ==14939== Address 0x1a8fcbc9 is not stack'd, malloc'd or (recently) free'd
+ *
+ * Curieusement, un appel à PyErr_PrintEx(1) corrige l'effet, alors qu'un
+ * appel à PyErr_PrintEx(0) ne change rien.
+ *
+ * La seule différence de l'instruction set_sys_last_vars réside en quelques
+ * lignes dans le code de l'interpréteur Python :
+ *
+ * if (set_sys_last_vars) {
+ * _PySys_SetObjectId(&PyId_last_type, exception);
+ * _PySys_SetObjectId(&PyId_last_value, v);
+ * _PySys_SetObjectId(&PyId_last_traceback, tb);
+ * }
+ *
+ * L'explication n'est pas encore déterminé : bogue dans Chrysalide ou dans Python ?
+ * L'ajout des éléments dans le dictionnaire du module sys ajoute une référence
+ * à ces éléments.
+ *
+ * On reproduit ici le comportement du code correcteur avec PySys_SetObject().
+ */
+
+ PySys_SetObject("last_type", err_type);
+ PySys_SetObject("last_value", err_value);
+ PySys_SetObject("last_traceback", err_traceback);
+
+ Py_XDECREF(err_traceback);
+ Py_XDECREF(err_value);
+ Py_XDECREF(err_type);
+
+ log_plugin_simple_message(LMT_EXT_ERROR, msg);
+
+ free(msg);
+
+ }
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* FONCTIONS GLOBALES DE CHRYSALIDE */
diff --git a/plugins/pychrysalide/bindings.h b/plugins/pychrysalide/bindings.h
index 1c63956..e9ee421 100644
--- a/plugins/pychrysalide/bindings.h
+++ b/plugins/pychrysalide/bindings.h
@@ -48,16 +48,15 @@ typedef struct _pyinit_details_t
{
bool standalone; /* Chargement depuis Python ? */
-
bool (* populate_extra) (void); /* Ajout de types ? */
-
} pyinit_details_t;
/* Implémente le point d'entrée pour l'initialisation de Python. */
PyObject *init_python_pychrysalide_module(const pyinit_details_t *);
-
+/* Présente dans le journal une exception survenue. */
+void log_pychrysalide_exception(const char *, ...);
diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c
index e815e25..3c551c7 100644
--- a/plugins/pychrysalide/core.c
+++ b/plugins/pychrysalide/core.c
@@ -368,146 +368,6 @@ G_MODULE_EXPORT gpointer chrysalide_plugin_build_type_instance(GPluginModule *pl
-/******************************************************************************
-* *
-* Paramètres : prefix = message d'introduction à faire apparaître à l'écran.*
-* *
-* Description : Présente dans le journal une exception survenue. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void log_pychrysalide_exception(const char *prefix, ...)
-{
- va_list ap; /* Compléments argumentaires */
- char *msg; /* Message complet à imprimer */
- PyObject *err_type; /* Type d'erreur Python */
- PyObject *err_value; /* Instance Python d'erreur */
- PyObject *err_traceback; /* Trace Python associée */
- PyObject *err_string; /* Description Python d'erreur */
- const char *err_msg; /* Représentation humaine */
-
- assert(PyGILState_Check() == 1);
-
- if (PyErr_Occurred())
- {
- /* Base de la communication */
-
- va_start(ap, prefix);
-
- vasprintf(&msg, prefix, ap);
-
- va_end(ap);
-
- /* Détails complémentaires */
-
- PyErr_Fetch(&err_type, &err_value, &err_traceback);
-
- PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
-
- if (err_traceback == NULL)
- {
- err_traceback = Py_None;
- Py_INCREF(err_traceback);
- }
-
- PyException_SetTraceback(err_value, err_traceback);
-
- if (err_value == NULL)
- msg = stradd(msg, _(": no extra information is provided..."));
-
- else
- {
- err_string = PyObject_Str(err_value);
- err_msg = PyUnicode_AsUTF8(err_string);
-
- msg = stradd(msg, ": ");
- msg = stradd(msg, err_msg);
-
- Py_DECREF(err_string);
-
- }
-
- /**
- * Bien que la documentation précise que la fonction PyErr_Fetch()
- * transfère la propritété des éléments retournés, la pratique
- * montre que le programme plante à la terminaison en cas d'exception.
- *
- * C'est par exemple le cas quand un greffon Python ne peut se lancer
- * correctement ; l'exception est alors levée à partir de la fonction
- * create_python_plugin() et le plantage intervient en sortie d'exécution,
- * au moment de la libération de l'extension Python :
- *
- * ==14939== Jump to the invalid address stated on the next line
- * ==14939== at 0x1A8FCBC9: ???
- * ==14939== by 0x53DCDB2: g_object_unref (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5800.3)
- * ==14939== by 0x610F834: on_plugin_ref_toggle (pglist.c:370)
- * ==14939== by 0x610F31A: exit_all_plugins (pglist.c:153)
- * ==14939== by 0x10AD19: main (main.c:440)
- * ==14939== Address 0x1a8fcbc9 is not stack'd, malloc'd or (recently) free'd
- *
- * Curieusement, un appel à PyErr_PrintEx(1) corrige l'effet, alors qu'un
- * appel à PyErr_PrintEx(0) ne change rien.
- *
- * La seule différence de l'instruction set_sys_last_vars réside en quelques
- * lignes dans le code de l'interpréteur Python :
- *
- * if (set_sys_last_vars) {
- * _PySys_SetObjectId(&PyId_last_type, exception);
- * _PySys_SetObjectId(&PyId_last_value, v);
- * _PySys_SetObjectId(&PyId_last_traceback, tb);
- * }
- *
- * L'explication n'est pas encore déterminé : bogue dans Chrysalide ou dans Python ?
- * L'ajout des éléments dans le dictionnaire du module sys ajoute une référence
- * à ces éléments.
- *
- * On reproduit ici le comportement du code correcteur avec PySys_SetObject().
- */
-
- PySys_SetObject("last_type", err_type);
- PySys_SetObject("last_value", err_value);
- PySys_SetObject("last_traceback", err_traceback);
-
- Py_XDECREF(err_traceback);
- Py_XDECREF(err_value);
- Py_XDECREF(err_type);
-
- log_plugin_simple_message(LMT_ERROR, msg);
-
- free(msg);
-
- }
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* ---------------------------------------------------------------------------------- */
/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
/* ---------------------------------------------------------------------------------- */
@@ -685,8 +545,6 @@ static GPluginModule *create_python_plugin(const char *modname, const char *file
result = G_PLUGIN_MODULE(pygobject_get(instance));
- ///result->filename = strdup(filename);
-
/**
* L'instance Python et l'objet GLib résultant sont un même PyGObject.
*
@@ -696,13 +554,11 @@ static GPluginModule *create_python_plugin(const char *modname, const char *file
Py_DECREF(module);
- printf(" -> REF: %p %u\n", result, G_OBJECT(result)->ref_count);
-
return result;
no_instance:
- //log_pychrysalide_exception(_("An error occured when building the 'AutoLoad' instance"));
+ log_pychrysalide_exception(_("An error occured when building the 'AutoLoad' instance"));
no_class:
@@ -714,7 +570,7 @@ static GPluginModule *create_python_plugin(const char *modname, const char *file
Py_XDECREF(module);
- //log_pychrysalide_exception(_("An error occured when importing '%s'"), modname);
+ log_pychrysalide_exception(_("An error occured when importing '%s'"), modname);
bad_exit: