[folks] Eds.Backend: use a safe remove-while-iterating pattern



commit ff3ebb6595730e7c1e7633369da53dfef3f161fa
Author: Simon McVittie <simon mcvittie collabora co uk>
Date:   Tue Mar 19 15:22:23 2013 +0000

    Eds.Backend: use a safe remove-while-iterating pattern
    
    Otherwise, if we unprepare with more than 0 address books, we'll remove
    from a hash map while iterating over it, resulting in a crash.

 backends/eds/eds-backend.vala |   42 ++++++++++++++++++++++------------------
 1 files changed, 23 insertions(+), 19 deletions(-)
---
diff --git a/backends/eds/eds-backend.vala b/backends/eds/eds-backend.vala
index ba9580d..4b8383e 100644
--- a/backends/eds/eds-backend.vala
+++ b/backends/eds/eds-backend.vala
@@ -133,25 +133,19 @@ public class Folks.Backends.Eds.Backend : Folks.Backend
             }
         }
 
-      /* Keep persona stores to remove in a separate array so we don't
-       * invalidate the list we are iterating over. */
-      PersonaStore[] stores_to_remove = {};
-      
-      foreach (PersonaStore store in this._persona_stores.values)
+      var iter = this._persona_stores.values.iterator ();
+
+      while (iter.next ())
         {
+          var store = iter.get ();
+
           if (!storeids.contains (store.id))
             {
-              stores_to_remove += store;
+              this._remove_address_book (store, false, iter);
               stores_changed = true;
             }
         }
-        
-      for (int i = 0; i < stores_to_remove.length; ++i)
-        {
-          this._remove_address_book (stores_to_remove[i], false);
-        }
-        
-      /* Finally, if anything changed, emit the persona-stores notification. */
+
       if (stores_changed)
         {
           this.notify_property ("persona-stores");
@@ -252,10 +246,10 @@ public class Folks.Backends.Eds.Backend : Folks.Backend
         {
           this._prepare_pending = true;
 
-          foreach (var persona_store in this._persona_stores.values)
-            {
-              this._remove_address_book (persona_store);
-            }
+          var iter = this._persona_stores.values.iterator ();
+
+          while (iter.next ())
+            this._remove_address_book (iter.get (), true, iter);
 
           this._ab_sources.source_added.disconnect (this._ab_source_list_changed_cb);
           this._ab_sources.source_enabled.disconnect (this._ab_source_list_changed_cb);
@@ -345,11 +339,21 @@ public class Folks.Backends.Eds.Backend : Folks.Backend
       this.enable_persona_store (store);
     }
 
-  private void _remove_address_book (Folks.PersonaStore store, bool notify = true)
+  private void _remove_address_book (Folks.PersonaStore store,
+      bool notify = true,
+      Iterator<Folks.PersonaStore>? iter = null)
     {
       debug ("Removing address book '%s'.", store.id);
 
-      this._persona_stores.unset (store.id);
+      if (iter != null)
+        {
+          assert (store == iter.get ());
+          iter.remove ();
+        }
+      else
+        {
+          this._persona_stores.unset (store.id);
+        }
 
       this.persona_store_removed (store);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]