summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/bindings.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/bindings.c')
-rw-r--r--plugins/pychrysalide/bindings.c120
1 files changed, 119 insertions, 1 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 */