← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~mterry/indicator-appmenu/fix-empathy-contact-crash into lp:indicator-appmenu

 

Michael Terry has proposed merging lp:~mterry/indicator-appmenu/fix-empathy-contact-crash into lp:indicator-appmenu.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)
Related bugs:
  #696897 clicking on 'contact' menu in empathy chat window reloads the menubar in Unity
  https://bugs.launchpad.net/bugs/696897

For more details, see:
https://code.launchpad.net/~mterry/indicator-appmenu/fix-empathy-contact-crash/+merge/47579

Empathy swaps out the menu for the Contact toplevel entry whenever a contact window gets focus.  Since indicator-appmenu isn't well prepared for that, it kept a pointer around to the old menu.  Then it crashed when the user tried to use it.

To fully fix this, I'd ideally like to add support for using the new menu, but for now, I'm interested in just stopping us from crashing.  So here's a patch to NULL out the entry's menu when it is destroyed by libdbusmenu.

With this patch alone, the empty menu stops scrubbing motions.  There's a separate patch I'm filing against unity to fix that.
-- 
https://code.launchpad.net/~mterry/indicator-appmenu/fix-empathy-contact-crash/+merge/47579
Your team ayatana-commits is subscribed to branch lp:indicator-appmenu.
=== modified file 'src/window-menus.c'
--- src/window-menus.c	2011-01-25 18:21:55 +0000
+++ src/window-menus.c	2011-01-26 19:52:40 +0000
@@ -207,6 +207,28 @@
 	return;
 }
 
+static void
+entry_free(IndicatorObjectEntry * entry)
+{
+	g_return_if_fail(entry != NULL);
+
+	if (entry->label != NULL) {
+		g_object_unref(entry->label);
+		entry->label = NULL;
+	}
+	if (entry->image != NULL) {
+		g_object_unref(entry->image);
+		entry->image = NULL;
+	}
+	if (entry->menu != NULL) {
+		g_signal_handlers_disconnect_by_func(entry->menu, G_CALLBACK(gtk_widget_destroyed), &entry->menu);
+		g_object_unref(entry->menu);
+		entry->menu = NULL;
+	}
+
+	g_free(entry);
+}
+
 /* Free memory */
 static void
 window_menus_finalize (GObject *object)
@@ -220,15 +242,9 @@
 		for (i = 0; i < priv->entries->len; i++) {
 			IndicatorObjectEntry * entry;
 			entry = g_array_index(priv->entries, IndicatorObjectEntry *, i);
-			
-			if (entry->label != NULL) {
-				g_object_unref(entry->label);
-			}
-			if (entry->menu != NULL) {
-				g_object_unref(entry->menu);
-			}
+			entry_free(entry);
 		}
-		g_array_free(priv->entries, TRUE);
+		g_array_free(priv->entries, FALSE);
 		priv->entries = NULL;
 	}
 
@@ -659,6 +675,7 @@
 	} else {
 		g_object_ref(entry->menu);
 		gtk_menu_detach(entry->menu);
+		g_signal_connect(entry->menu, "destroy", G_CALLBACK(gtk_widget_destroyed), &entry->menu);
 	}
 
 	g_signal_connect(G_OBJECT(newentry), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_changed), entry);
@@ -704,7 +721,7 @@
 
 	g_signal_emit(G_OBJECT(user_data), signals[ENTRY_REMOVED], 0, entry, TRUE);
 
-	g_free(entry);
+	entry_free(entry);
 
 	return;
 }


Follow ups