changeset 25605:9c0337d4b878

Fix the crash/leaks in statusbox *** Plucked rev 0cb6e54b (darkrain42@pidgin.im): Look up the old image before we store the new one in the hash table. Looking up the new image and then unref:ing it (hence freeing the data and subsequently returning it) is not good. This was causing problems with changing buddy icons while using mystatusbox. Refs #9120. *** Plucked rev d25c9ed7 (darkrain42@pidgin.im): Don't leak image refs in gtkstatusbox and assertion failure in nullprpl purple_imgstore_new_from_file gives us a ref and pidgin_status_box_set_buddy_icon also takes a ref.
author Paul Aurich <paul@darkrain42.org>
date Wed, 06 May 2009 18:58:47 +0000
parents c18f78b2db6b
children 2260e5b0ca91
files libpurple/buddyicon.c libpurple/protocols/null/nullprpl.c pidgin/gtkstatusbox.c
diffstat 3 files changed, 23 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/buddyicon.c	Mon May 04 00:12:34 2009 +0000
+++ b/libpurple/buddyicon.c	Wed May 06 18:58:47 2009 +0000
@@ -753,6 +753,8 @@
 	}
 	unref_filename(old_icon);
 
+	old_img = g_hash_table_lookup(pointer_icon_cache, account);
+
 	if (img)
 		g_hash_table_insert(pointer_icon_cache, account, img);
 	else
@@ -770,7 +772,7 @@
 			prpl_info->set_buddy_icon(gc, img);
 	}
 
-	if ((old_img = g_hash_table_lookup(pointer_icon_cache, account)))
+	if (old_img)
 		purple_imgstore_unref(old_img);
 	else if (old_icon)
 	{
--- a/libpurple/protocols/null/nullprpl.c	Mon May 04 00:12:34 2009 +0000
+++ b/libpurple/protocols/null/nullprpl.c	Wed May 06 18:58:47 2009 +0000
@@ -927,7 +927,8 @@
 static void nullprpl_set_buddy_icon(PurpleConnection *gc,
                                     PurpleStoredImage *img) {
  purple_debug_info("nullprpl", "setting %s's buddy icon to %s\n",
-                   gc->account->username, purple_imgstore_get_filename(img));
+                   gc->account->username,
+                   img ? purple_imgstore_get_filename(img) : "(null)");
 }
 
 static void nullprpl_remove_group(PurpleConnection *gc, PurpleGroup *group) {
--- a/pidgin/gtkstatusbox.c	Mon May 04 00:12:34 2009 +0000
+++ b/pidgin/gtkstatusbox.c	Wed May 06 18:58:47 2009 +0000
@@ -417,16 +417,15 @@
 		PurpleStoredImage *img = NULL;
 
 		if (filename != NULL)
-		{
-			gchar *contents;
-			gsize size;
-			if (g_file_get_contents(filename, &contents, &size, NULL))
-			{
-				img = purple_imgstore_add(contents, size, filename);
-			}
-		}
+			img = purple_imgstore_new_from_file(filename);
 
 		pidgin_status_box_set_buddy_icon(status_box, img);
+		if (img)
+			/*
+			 * purple_imgstore_new gives us a reference and
+			 * pidgin_status_box_set_buddy_icon also takes one.
+			 */
+			purple_imgstore_unref(img);
 	}
 
 	status_box->hand_cursor = gdk_cursor_new (GDK_HAND2);
@@ -1496,6 +1495,13 @@
 				if (filename)
 					data = pidgin_convert_buddy_icon(plug, filename, &len);
 				img = purple_buddy_icons_set_account_icon(box->account, data, len);
+				if (img)
+					/*
+					 * set_account_icon doesn't give us a reference, but we
+					 * unref one below (for the other code path)
+					 */
+					purple_imgstore_ref(img);
+
 				purple_account_set_buddy_icon_path(box->account, filename);
 
 				purple_account_set_bool(box->account, "use-global-buddyicon", (filename != NULL));
@@ -1515,7 +1521,7 @@
 					size_t len = 0;
 					if (filename)
 						data = pidgin_convert_buddy_icon(plug, filename, &len);
-					img = purple_buddy_icons_set_account_icon(account, data, len);
+					purple_buddy_icons_set_account_icon(account, data, len);
 					purple_account_set_buddy_icon_path(account, filename);
 				}
 			}
@@ -1523,17 +1529,12 @@
 
 		/* Even if no accounts were processed, load the icon that was set. */
 		if (filename != NULL)
-		{
-			gchar *contents;
-			gsize size;
-			if (g_file_get_contents(filename, &contents, &size, NULL))
-			{
-				img = purple_imgstore_add(contents, size, filename);
-			}
-		}
+			img = purple_imgstore_new_from_file(filename);
 	}
 
 	pidgin_status_box_set_buddy_icon(box, img);
+	if (img)
+		purple_imgstore_unref(img);
 }
 
 static void