From f22f73bcbdb6510169c8b7c7c3fea842750c6fe5 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 18 Aug 2022 21:05:33 +0200 Subject: Handle the Python Global Interpreter Lock with more care. --- plugins/pychrysalide/analysis/type.c | 30 ++++++++++++++++ plugins/pychrysalide/core.c | 67 +++++++++++------------------------- plugins/pychrysalide/core.h | 3 -- plugins/pychrysalide/format/symbol.c | 5 +++ plugins/pychrysalide/gui/item.c | 60 +++++++++++--------------------- plugins/pychrysalide/helpers.c | 2 ++ 6 files changed, 77 insertions(+), 90 deletions(-) diff --git a/plugins/pychrysalide/analysis/type.c b/plugins/pychrysalide/analysis/type.c index 86a0ffb..357d381 100644 --- a/plugins/pychrysalide/analysis/type.c +++ b/plugins/pychrysalide/analysis/type.c @@ -220,6 +220,7 @@ static void py_data_type_init_gclass(GDataTypeClass *class, gpointer unused) static guint py_data_type_hash_wrapper(const GDataType *type) { guint result; /* Empreinte à renvoyer */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *pyret; /* Bilan de consultation */ @@ -234,6 +235,8 @@ static guint py_data_type_hash_wrapper(const GDataType *type) result = 0; + gstate = PyGILState_Ensure(); + pyobj = pygobject_new(G_OBJECT(type)); if (has_python_method(pyobj, "_hash")) @@ -252,6 +255,8 @@ static guint py_data_type_hash_wrapper(const GDataType *type) Py_DECREF(pyobj); + PyGILState_Release(gstate); + return result; } @@ -272,6 +277,7 @@ static guint py_data_type_hash_wrapper(const GDataType *type) static GDataType *py_data_type_dup_wrapper(const GDataType *type) { GDataType *result; /* Copie à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *pyret; /* Bilan de consultation */ @@ -287,6 +293,8 @@ static GDataType *py_data_type_dup_wrapper(const GDataType *type) result = NULL; + gstate = PyGILState_Ensure(); + pyobj = pygobject_new(G_OBJECT(type)); if (has_python_method(pyobj, "_dup")) @@ -308,6 +316,8 @@ static GDataType *py_data_type_dup_wrapper(const GDataType *type) Py_DECREF(pyobj); + PyGILState_Release(gstate); + return result; } @@ -329,6 +339,7 @@ static GDataType *py_data_type_dup_wrapper(const GDataType *type) static char *py_data_type_to_string_wrapper(const GDataType *type, bool include) { char *result; /* Etiquette à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *arg; /* Version Python de l'argument*/ PyObject *args; /* Arguments pour l'appel */ @@ -349,6 +360,8 @@ static char *py_data_type_to_string_wrapper(const GDataType *type, bool include) result = NULL; + gstate = PyGILState_Ensure(); + pyobj = pygobject_new(G_OBJECT(type)); if (has_python_method(pyobj, "_to_string")) @@ -375,6 +388,8 @@ static char *py_data_type_to_string_wrapper(const GDataType *type, bool include) Py_DECREF(pyobj); + PyGILState_Release(gstate); + return result; } @@ -395,6 +410,7 @@ static char *py_data_type_to_string_wrapper(const GDataType *type, bool include) static bool py_data_type_handle_namespaces_wrapper(const GDataType *type) { bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *pyret; /* Bilan de consultation */ @@ -411,6 +427,8 @@ static bool py_data_type_handle_namespaces_wrapper(const GDataType *type) result = true; + gstate = PyGILState_Ensure(); + pyobj = pygobject_new(G_OBJECT(type)); if (has_python_method(pyobj, "_handle_namespaces")) @@ -425,6 +443,8 @@ static bool py_data_type_handle_namespaces_wrapper(const GDataType *type) Py_DECREF(pyobj); + PyGILState_Release(gstate); + return result; } @@ -445,6 +465,7 @@ static bool py_data_type_handle_namespaces_wrapper(const GDataType *type) static bool py_data_type_is_pointer_wrapper(const GDataType *type) { bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *pyret; /* Bilan de consultation */ @@ -461,6 +482,8 @@ static bool py_data_type_is_pointer_wrapper(const GDataType *type) result = false; + gstate = PyGILState_Ensure(); + pyobj = pygobject_new(G_OBJECT(type)); if (has_python_method(pyobj, "_is_pointer")) @@ -475,6 +498,8 @@ static bool py_data_type_is_pointer_wrapper(const GDataType *type) Py_DECREF(pyobj); + PyGILState_Release(gstate); + return result; } @@ -495,6 +520,7 @@ static bool py_data_type_is_pointer_wrapper(const GDataType *type) static bool py_data_type_is_reference_wrapper(const GDataType *type) { bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *pyret; /* Bilan de consultation */ @@ -511,6 +537,8 @@ static bool py_data_type_is_reference_wrapper(const GDataType *type) result = false; + gstate = PyGILState_Ensure(); + pyobj = pygobject_new(G_OBJECT(type)); if (has_python_method(pyobj, "_is_reference")) @@ -525,6 +553,8 @@ static bool py_data_type_is_reference_wrapper(const GDataType *type) Py_DECREF(pyobj); + PyGILState_Release(gstate); + return result; } diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c index ef119fb..c062d15 100644 --- a/plugins/pychrysalide/core.c +++ b/plugins/pychrysalide/core.c @@ -85,9 +85,6 @@ static bool _standalone = true; /* Réceptacle pour le chargement forcé */ static PyObject *_chrysalide_module = NULL; -/* Conservation des informations du thread principal */ -static PyThreadState *_main_tstate = NULL; - /* Fournit la révision du programme global. */ static PyObject *py_chrysalide_revision(PyObject *, PyObject *); @@ -656,7 +653,6 @@ 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 */ @@ -736,17 +732,8 @@ 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, @@ -808,6 +795,7 @@ static void load_python_plugins(GPluginModule *plugin) G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) { bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ int ret; /* Bilan de préparatifs */ _standalone = false; @@ -825,6 +813,8 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) Py_Initialize(); + gstate = PyGILState_Ensure(); + PySys_SetArgv(0, (wchar_t *[]) { NULL }); _chrysalide_module = PyImport_ImportModule("pychrysalide"); @@ -842,9 +832,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) result = (_chrysalide_module != NULL); - _main_tstate = PyThreadState_Get(); - - PyEval_ReleaseLock(); + PyGILState_Release(gstate); cpi_done: @@ -867,10 +855,16 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + + gstate = PyGILState_Ensure(); + clear_all_accesses_to_python_modules(); Py_XDECREF(_chrysalide_module); + PyGILState_Release(gstate); + } @@ -911,6 +905,7 @@ static void free_native_plugin_type(PyTypeObject *type) G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin, PluginAction action) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ size_t count; /* Quantité de greffons chargés*/ PyTypeObject *parent; /* Type Python pour greffon */ PyObject *module; /* Module à recompléter */ @@ -922,6 +917,8 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin, int ret; /* Bilan d'un appel */ PyTypeObject *type; /* Nouveau type dynamique */ + gstate = PyGILState_Ensure(); + if (action == PGA_NATIVE_PLUGINS_LOADED) { /* Intégration des greffons natifs en Python */ @@ -982,6 +979,8 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin, } + PyGILState_Release(gstate); + } @@ -1002,17 +1001,13 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *plugin, G_MODULE_EXPORT gpointer chrysalide_plugin_build_type_instance(GPluginModule *plugin, PluginAction action, GType type) { gpointer result; /* Instance à retourner */ - PyThreadState *tstate; /* Contexte d'environnement */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyTypeObject *pytype; /* Classe Python concernée */ PyObject *instance; /* Initialisation forcée */ result = NULL; - if (!_standalone) - { - tstate = get_pychrysalide_main_tstate(); - PyEval_RestoreThread(tstate); - } + gstate = PyGILState_Ensure(); pytype = pygobject_lookup_class(type); @@ -1025,31 +1020,7 @@ G_MODULE_EXPORT gpointer chrysalide_plugin_build_type_instance(GPluginModule *pl } - if (!_standalone) - PyEval_SaveThread(); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit les informations du thread principal. * -* * -* Retour : Indications utiles à Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyThreadState *get_pychrysalide_main_tstate(void) -{ - PyThreadState *result; /* Indications à retourner */ - - result = _main_tstate; + PyGILState_Release(gstate); return result; @@ -1078,6 +1049,8 @@ void log_pychrysalide_exception(const char *prefix, ...) 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 */ diff --git a/plugins/pychrysalide/core.h b/plugins/pychrysalide/core.h index 6a7b9d1..88c4140 100644 --- a/plugins/pychrysalide/core.h +++ b/plugins/pychrysalide/core.h @@ -55,9 +55,6 @@ G_MODULE_EXPORT void chrysalide_plugin_on_plugins_loaded(GPluginModule *, Plugin /* Crée une instance à partir d'un type dynamique externe. */ G_MODULE_EXPORT gpointer chrysalide_plugin_build_type_instance(GPluginModule *, PluginAction, GType); -/* Fournit les informations du thread principal. */ -PyThreadState *get_pychrysalide_main_tstate(void); - /* Présente dans le journal une exception survenue. */ void log_pychrysalide_exception(const char *, ...); diff --git a/plugins/pychrysalide/format/symbol.c b/plugins/pychrysalide/format/symbol.c index e2f2dda..1559b9a 100644 --- a/plugins/pychrysalide/format/symbol.c +++ b/plugins/pychrysalide/format/symbol.c @@ -215,6 +215,7 @@ static void py_binary_symbol_init_gclass(GBinSymbolClass *class, gpointer unused static char *py_binary_symbol_get_label_wrapper(const GBinSymbol *symbol) { char *result; /* Etiquette à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *pyret; /* Bilan de consultation */ @@ -229,6 +230,8 @@ static char *py_binary_symbol_get_label_wrapper(const GBinSymbol *symbol) result = NULL; + gstate = PyGILState_Ensure(); + pyobj = pygobject_new(G_OBJECT(symbol)); if (has_python_method(pyobj, "_get_label")) @@ -247,6 +250,8 @@ static char *py_binary_symbol_get_label_wrapper(const GBinSymbol *symbol) Py_DECREF(pyobj); + PyGILState_Release(gstate); + return result; } diff --git a/plugins/pychrysalide/gui/item.c b/plugins/pychrysalide/gui/item.c index 2046587..eb140fb 100644 --- a/plugins/pychrysalide/gui/item.c +++ b/plugins/pychrysalide/gui/item.c @@ -291,19 +291,16 @@ static GtkWidget *py_editor_item_get_widget_wrapper(const GEditorItem *item) static void py_editor_item_change_content_wrapper(GEditorItem *item, GLoadedContent *old, GLoadedContent *new) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ - PyThreadState *tstate; /* Contexte d'environnement */ PyObject *pyold; /* Conversion ou None */ PyObject *pynew; /* Conversion ou None */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Retour de Python */ - pyobj = pygobject_new(G_OBJECT(item)); - - tstate = get_pychrysalide_main_tstate(); + gstate = PyGILState_Ensure(); - if (tstate != NULL) - PyEval_RestoreThread(tstate); + pyobj = pygobject_new(G_OBJECT(item)); if (has_python_method(pyobj, "_change_content")) { @@ -334,8 +331,7 @@ static void py_editor_item_change_content_wrapper(GEditorItem *item, GLoadedCont } - if (tstate != NULL) - PyEval_SaveThread(); + PyGILState_Release(gstate); } @@ -356,19 +352,16 @@ static void py_editor_item_change_content_wrapper(GEditorItem *item, GLoadedCont static void py_editor_item_change_view_wrapper(GEditorItem *item, GLoadedPanel *old, GLoadedPanel *new) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ - PyThreadState *tstate; /* Contexte d'environnement */ PyObject *pyold; /* Conversion ou None */ PyObject *pynew; /* Conversion ou None */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Retour de Python */ - pyobj = pygobject_new(G_OBJECT(item)); - - tstate = get_pychrysalide_main_tstate(); + gstate = PyGILState_Ensure(); - if (tstate != NULL) - PyEval_RestoreThread(tstate); + pyobj = pygobject_new(G_OBJECT(item)); if (has_python_method(pyobj, "_change_view")) { @@ -399,8 +392,7 @@ static void py_editor_item_change_view_wrapper(GEditorItem *item, GLoadedPanel * } - if (tstate != NULL) - PyEval_SaveThread(); + PyGILState_Release(gstate); } @@ -420,17 +412,14 @@ static void py_editor_item_change_view_wrapper(GEditorItem *item, GLoadedPanel * static void py_editor_item_update_view_wrapper(GEditorItem *item, GLoadedPanel *panel) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ - PyThreadState *tstate; /* Contexte d'environnement */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Retour de Python */ - pyobj = pygobject_new(G_OBJECT(item)); - - tstate = get_pychrysalide_main_tstate(); + gstate = PyGILState_Ensure(); - if (tstate != NULL) - PyEval_RestoreThread(tstate); + pyobj = pygobject_new(G_OBJECT(item)); if (has_python_method(pyobj, "_update_view")) { @@ -444,8 +433,7 @@ static void py_editor_item_update_view_wrapper(GEditorItem *item, GLoadedPanel * } - if (tstate != NULL) - PyEval_SaveThread(); + PyGILState_Release(gstate); } @@ -466,17 +454,14 @@ static void py_editor_item_update_view_wrapper(GEditorItem *item, GLoadedPanel * static void py_editor_item_track_cursor_wrapper(GEditorItem *item, GLoadedPanel *panel, const GLineCursor *cursor) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ - PyThreadState *tstate; /* Contexte d'environnement */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Retour de Python */ - pyobj = pygobject_new(G_OBJECT(item)); - - tstate = get_pychrysalide_main_tstate(); + gstate = PyGILState_Ensure(); - if (tstate != NULL) - PyEval_RestoreThread(tstate); + pyobj = pygobject_new(G_OBJECT(item)); if (has_python_method(pyobj, "_track_cursor")) { @@ -491,8 +476,7 @@ static void py_editor_item_track_cursor_wrapper(GEditorItem *item, GLoadedPanel } - if (tstate != NULL) - PyEval_SaveThread(); + PyGILState_Release(gstate); } @@ -513,17 +497,14 @@ static void py_editor_item_track_cursor_wrapper(GEditorItem *item, GLoadedPanel static void py_editor_item_focus_cursor_wrapper(GEditorItem *item, GLoadedContent *content, const GLineCursor *cursor) { + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ - PyThreadState *tstate; /* Contexte d'environnement */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Retour de Python */ - pyobj = pygobject_new(G_OBJECT(item)); - - tstate = get_pychrysalide_main_tstate(); + gstate = PyGILState_Ensure(); - if (tstate != NULL) - PyEval_RestoreThread(tstate); + pyobj = pygobject_new(G_OBJECT(item)); if (has_python_method(pyobj, "_focus_cursor")) { @@ -538,8 +519,7 @@ static void py_editor_item_focus_cursor_wrapper(GEditorItem *item, GLoadedConten } - if (tstate != NULL) - PyEval_SaveThread(); + PyGILState_Release(gstate); } diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c index 8e7c10c..e0a3340 100644 --- a/plugins/pychrysalide/helpers.c +++ b/plugins/pychrysalide/helpers.c @@ -234,6 +234,8 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args PyObject *traceback; /* Pile d'appels de l'exception*/ PyObject *refmsg; /* Message de référence */ + assert(PyGILState_Check() == 1); + /* Exécution */ result = NULL; -- cgit v0.11.2-87-g4458