diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2025-01-13 07:34:49 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2025-01-13 07:34:49 (GMT) | 
| commit | 59ab0336eaab192ca2f02b67d143a1ba4d1aac2b (patch) | |
| tree | 824215b03d19bd8a188cc480b376d2ff882773eb /plugins/pychrysalide/bindings.c | |
| parent | 71367e25e95b90b34891ec88083a52e0e0f60f13 (diff) | |
Handle load errors due to buggy Python plugins.
Diffstat (limited to 'plugins/pychrysalide/bindings.c')
| -rw-r--r-- | plugins/pychrysalide/bindings.c | 120 | 
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                          */  | 
