changeset 21400:cb9e962d4f7f

Fix iterating over accounts_signed_on_elsewhere while doing things that will cause it to change.
author Will Thompson <will.thompson@collabora.co.uk>
date Sat, 03 Nov 2007 16:32:28 +0000
parents d2bd7eae1c2c
children c1c7e28223f8
files pidgin/gtkblist.c
diffstat 1 files changed, 15 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin/gtkblist.c	Sat Nov 03 14:35:09 2007 +0000
+++ b/pidgin/gtkblist.c	Sat Nov 03 16:32:28 2007 +0000
@@ -4472,15 +4472,25 @@
 ignore_elsewhere_accounts(PidginBuddyList *gtkblist)
 {
 	PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
-	GList *l;
-
-	for (l = priv->accounts_signed_on_elsewhere; l != NULL; l = l->next) {
+	GList *accounts_elsewhere, *l;
+
+	/* priv->accounts_signed_on_elsewhere gets changed in
+	 * update_account_error_state, which is called when
+	 * purple_account_clear_current_error emits account-error-changed. So
+	 * let's take a copy.
+	 *
+	 * (Or maybe we could just use while(priv->accounts_elsewhere) and rely
+	 * on it being ultimately reduced to NULL?  But that sounds fragile.)
+	 */
+	accounts_elsewhere = g_list_copy(priv->accounts_signed_on_elsewhere);
+
+	for (l = accounts_elsewhere; l != NULL; l = l->next)
+	{
 		PurpleAccount *account = l->data;
 		purple_account_clear_current_error(account);
 	}
 
-	g_list_free(priv->accounts_signed_on_elsewhere);
-	priv->accounts_signed_on_elsewhere = NULL;
+	g_list_free(accounts_elsewhere);
 
 	destroy_signed_on_elsewhere_minidialog(priv);
 }