From b2e519687ab410b6489b3ec02348ec5251e81b05 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sat, 3 Sep 2011 01:59:17 +0200 Subject: [PATCH] Add API to unload plugin module This is a workaround for a very complicated bug. When you have more than one ChimaraGlk widget opening the same plugin, then g_module_open() doesn't dlopen() the plugin again; instead, it just adds a reference to the open module. This means that all static variables in the module are not reinitialized when the Glk program starts running in the second ChimaraGlk widget. This problem needs to be solved either by eliminating the static variables from the plugins, or making sure that different ChimaraGlk widgets open their plugins separately. This commit does the latter, by adding API to unload the plugin module (chimara_glk_unload_plugin()) so that ChimaraGlk widgets that run the same program but not at the same time have the option to unload the plugin in one widget before loading it in the other. Specifically, this is the use case of Inform 7. This does not fix the use case where two separate ChimaraGlk widgets want to run the same program at the same time. --- libchimara/chimara-glk.c | 23 +++++++++++++++++++++-- libchimara/chimara-glk.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libchimara/chimara-glk.c b/libchimara/chimara-glk.c index 47c2b51..949f951 100644 --- a/libchimara/chimara-glk.c +++ b/libchimara/chimara-glk.c @@ -1257,8 +1257,7 @@ chimara_glk_run(ChimaraGlk *glk, const gchar *plugin, int argc, char *argv[], GE g_assert( g_module_supported() ); /* If there is already a module loaded, free it first -- you see, we want to * keep modules loaded as long as possible to avoid crashes in stack unwinding */ - if( priv->program && !g_module_close(priv->program) ) - g_warning( "Error closing module :%s", g_module_error() ); + chimara_glk_unload_plugin(glk); /* Open the module to run */ priv->program = g_module_open(plugin, G_MODULE_BIND_LAZY); @@ -1356,6 +1355,26 @@ chimara_glk_wait(ChimaraGlk *glk) gdk_threads_enter(); } +/** + * chimara_glk_unload_plugin: + * @glk: a #ChimaraGlk widget + * + * The plugin containing the Glk program is unloaded as late as possible before + * loading a new plugin, in order to prevent crashes while printing stack + * backtraces during debugging. Sometimes this behavior is not desirable. This + * function forces @glk to unload the plugin running in it. + * + * This function does nothing if there is no plugin loaded. + */ +void +chimara_glk_unload_plugin(ChimaraGlk *glk) +{ + g_return_if_fail(glk || CHIMARA_IS_GLK(glk)); + CHIMARA_GLK_USE_PRIVATE(glk, priv); + if( priv->program && !g_module_close(priv->program) ) + g_warning( "Error closing module :%s", g_module_error() ); +} + /** * chimara_glk_get_running: * @glk: a #ChimaraGlk widget diff --git a/libchimara/chimara-glk.h b/libchimara/chimara-glk.h index 37d2220..644de4d 100644 --- a/libchimara/chimara-glk.h +++ b/libchimara/chimara-glk.h @@ -124,6 +124,7 @@ guint chimara_glk_get_spacing(ChimaraGlk *glk); gboolean chimara_glk_run(ChimaraGlk *glk, const gchar *plugin, int argc, char *argv[], GError **error); void chimara_glk_stop(ChimaraGlk *glk); void chimara_glk_wait(ChimaraGlk *glk); +void chimara_glk_unload_plugin(ChimaraGlk *glk); gboolean chimara_glk_get_running(ChimaraGlk *glk); void chimara_glk_feed_char_input(ChimaraGlk *glk, guint32 keyval); void chimara_glk_feed_line_input(ChimaraGlk *glk, const gchar *text); -- 2.30.2