Add API to unload plugin module
authorPhilip Chimento <philip.chimento@gmail.com>
Fri, 2 Sep 2011 23:59:17 +0000 (01:59 +0200)
committerPhilip Chimento <philip.chimento@gmail.com>
Sun, 4 Sep 2011 20:00:24 +0000 (22:00 +0200)
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
libchimara/chimara-glk.h

index 47c2b51b014b320d625bfabc3cf1147d004902af..949f951d084669a9664115964d9225d67ac8b65c 100644 (file)
@@ -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
index 37d2220fb8776665cf07e947257dc01601db4fe6..644de4d4419432b7c0d418af31a801c0a46d06c6 100644 (file)
@@ -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);