Prevent extra "concurrent" PersonaStore.prepare() calls from one thread.
authorTravis Reitter <travis.reitter@collabora.co.uk>
Wed, 6 Jul 2011 21:48:43 +0000 (14:48 -0700)
committerJeremy Whiting <jpwhiting@kde.org>
Mon, 23 Jul 2012 15:11:16 +0000 (09:11 -0600)
The lock() calls which were in place only prevent concurrent calls from
different threads; however, the critical section could still be reached
from two async calls in the same thread a la:

backend.prepare.begin ((s,r) => {...});
backend.prepare.begin ((s,r) => {...});

The bodies of the handlers would not literally execute concurrently, but
would be interleaved if each were sufficiently long. Our fix simply
ignores any calls which happen while one is still working.

(yield backend.prepare(); yield backend.prepare(); was already safe, of
course)

Helps: bgo#652637 - Don't hold locks across async calls

backends/key-file/kf-persona-store.vala
backends/telepathy/lib/tpf-persona-store.vala
backends/tracker/lib/trf-persona-store.vala

index a5905a0..2c06e0d 100644 (file)
@@ -235,6 +235,7 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore
                               _("The relationship key file '%s' could not be loaded: %s"),
                               filename, e1.message);
                           this.removed ();
+                          this._prepare_pending = false;
                           return;
                         }
                     }
@@ -257,6 +258,7 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore
                               _("The relationship key file directory '%s' could not be created: %s"),
                               parent_dir.get_path (), e3.message);
                           this.removed ();
+                          this._prepare_pending = false;
                           return;
                         }
                     }
@@ -281,6 +283,7 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore
                               _("The relationship key file '%s' could not be created: %s"),
                               filename, e2.message);
                           this.removed ();
+                          this._prepare_pending = false;
                           return;
                         }
                     }
@@ -306,6 +309,7 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore
                 }
 
               this._is_prepared = true;
+              this._prepare_pending = false;
               this.notify_property ("is-prepared");
 
               /* We've finished loading all the personas we know about */
index c7eff9b..8afe084 100644 (file)
@@ -565,6 +565,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore
                   "(ID: %s)", this.id);
 
               this._is_prepared = true;
+              this._prepare_pending = false;
               this.notify_property ("is-prepared");
             }
           finally
index f442e8d..c53202f 100644 (file)
@@ -1144,6 +1144,10 @@ public class Trf.PersonaStore : Folks.PersonaStore
                   this.removed ();
                   throw new PersonaStoreError.INVALID_ARGUMENT (e3.message);
                 }
+              finally
+                {
+                  this._prepare_pending = false;
+                }
             }
           finally
             {