Revision: 1799 http://geany.svn.sourceforge.net/geany/?rev=1799&view=rev Author: ntrel Date: 2007-08-15 05:29:57 -0700 (Wed, 15 Aug 2007)
Log Message: ----------- Disconnect plugin callback signals when unloading plugins, to prevent a segfault when emitting signals.
Modified Paths: -------------- trunk/ChangeLog trunk/src/plugins.c
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-15 11:52:06 UTC (rev 1798) +++ trunk/ChangeLog 2007-08-15 12:29:57 UTC (rev 1799) @@ -4,6 +4,9 @@ Apply patch from Jeff Pohlmeyer to add document_remove() to the plugin API (thanks). Add document_open_files() to plugin API. + * src/plugins.c: + Disconnect plugin callback signals when unloading plugins, to prevent + a segfault when emitting signals.
2007-08-14 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
Modified: trunk/src/plugins.c =================================================================== --- trunk/src/plugins.c 2007-08-15 11:52:06 UTC (rev 1798) +++ trunk/src/plugins.c 2007-08-15 12:29:57 UTC (rev 1799) @@ -60,6 +60,8 @@ GModule *module; gchar *filename; // plugin filename (/path/libname.so) PluginFields fields; + gulong *signal_ids; // signal IDs to disconnect when unloading + gsize signal_ids_len;
PluginInfo* (*info) (); /* Returns plugin name, description */ void (*init) (GeanyData *data); /* Called when the plugin is enabled */ @@ -216,24 +218,32 @@ }
-// TODO: disconnect the callbacks when the plugin is unloaded. -static void add_callbacks(GeanyCallback *callbacks) +static void add_callbacks(Plugin *plugin, GeanyCallback *callbacks) { GeanyCallback *cb; - guint i = 0; + guint i, len = 0;
- do + while (TRUE) { - cb = &callbacks[i]; + cb = &callbacks[len]; if (!cb->signal_name || !cb->callback) break; + len++; + } + if (len == 0) + return;
- if (cb->after) - g_signal_connect_after(geany_object, cb->signal_name, cb->callback, cb->user_data); - else + plugin->signal_ids_len = len; + plugin->signal_ids = g_new(gulong, len); + + for (i = 0; i < len; i++) + { + cb = &callbacks[i]; + + plugin->signal_ids[i] = (cb->after) ? + g_signal_connect_after(geany_object, cb->signal_name, cb->callback, cb->user_data) : g_signal_connect(geany_object, cb->signal_name, cb->callback, cb->user_data); - i++; - } while (TRUE); + } }
@@ -322,7 +332,7 @@
g_module_symbol(module, "geany_callbacks", (void *) &callbacks); if (callbacks) - add_callbacks(callbacks); + add_callbacks(plugin, callbacks);
geany_debug("Loaded: %s (%s)", fname, NVL(plugin->info()->name, "<Unknown>")); @@ -330,6 +340,19 @@ }
+static void remove_callbacks(Plugin *plugin) +{ + guint i; + + if (plugin->signal_ids == NULL) + return; + + for (i = 0; i < plugin->signal_ids_len; i++) + g_signal_handler_disconnect(geany_object, plugin->signal_ids[i]); + g_free(plugin->signal_ids); +} + + static void plugin_free(Plugin *plugin) { @@ -344,6 +367,7 @@ else geany_debug("Unloaded: %s", plugin->filename);
+ remove_callbacks(plugin); g_free(plugin->filename); g_free(plugin); }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.