SF.net SVN: geany: [1799] trunk

ntrel at users.sourceforge.net ntrel at xxxxx
Wed Aug 15 12:29:59 UTC 2007


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.



More information about the Commits mailing list