Commit ce55fa2b authored by Philip Withnall's avatar Philip Withnall

telepathy: Yield subsequent Logger.prepare() calls if one is pending

If one PersonaStore began to prepare its Logger, then yielded on a D-Bus
call, another PersonaStore could begin to prepare its Logger and also
try to create a static D-Bus proxy (which is only supposed to be created
once). This is because the original async call hasn’t returned and set
Logger._logger by that point.

Fix this by keeping a queue of pending prepare() calls which is signalled
by the initial prepare() call once it finishes yielding.

Closes: https://bugzilla.gnome.org/show_bug.cgi?id=677633
parent ce34130c
......@@ -22,6 +22,7 @@ Bugs fixed:
• Bug 688923 — remove URLs (blog, free/busy, video, home page)
• Bug 689146 — disabling EDS address books does not remove personas
• Bug 689859 — core folks does not depend on telepathy
• Bug 677633 — Cannot delete favourite
API changes:
• Add Backend.enable_persona_store and disable_persona_store.
......
......@@ -43,10 +43,19 @@ private interface LoggerIface : Object
ObjectPath account_path, string[] added, string[] removed);
}
/* See: https://mail.gnome.org/archives/vala-list/2011-June/msg00008.html */
[Compact]
private class DelegateWrapper
{
public SourceFunc cb;
}
internal class Logger : GLib.Object
{
private static DBusConnection _dbus_conn;
private static LoggerIface _logger;
private static DelegateWrapper[] _prepare_waiters = null;
private uint _logger_watch_id;
public signal void invalidated ();
......@@ -77,22 +86,48 @@ internal class Logger : GLib.Object
public async void prepare () throws GLib.Error
{
if (Logger._logger == null)
if (Logger._logger == null && Logger._prepare_waiters == null)
{
/* If this is the first call to prepare(), start some async calls. We
* then yield to the main thread. Any subsequent calls to prepare()
* will have their continuations added to the _prepare_waiters list,
* and will be signalled once the first call returns.
* See: https://bugzilla.gnome.org/show_bug.cgi?id=677633 */
Logger._prepare_waiters = new DelegateWrapper[0];
/* Create a logger proxy for favourites support */
var dbus_conn = yield Bus.get (BusType.SESSION);
Logger._logger = yield dbus_conn.get_proxy<LoggerIface> (
"org.freedesktop.Telepathy.Logger",
"/org/freedesktop/Telepathy/Logger");
/* Failure? */
if (Logger._logger == null)
if (Logger._logger != null)
{
this.invalidated ();
return;
Logger._dbus_conn = dbus_conn;
}
Logger._dbus_conn = dbus_conn;
/* Wake up any waiters. */
foreach (unowned DelegateWrapper wrapper in Logger._prepare_waiters)
{
wrapper.cb ();
}
Logger._prepare_waiters = null;
}
else if (Logger._logger == null && Logger._prepare_waiters != null)
{
/* Yield until the first ongoing prepare() call finishes. */
var wrapper = new DelegateWrapper ();
wrapper.cb = prepare.callback;
Logger._prepare_waiters += (owned) wrapper;
yield;
}
/* Failure? */
if (Logger._logger == null)
{
this.invalidated ();
return;
}
this._logger_watch_id = Bus.watch_name_on_connection (Logger._dbus_conn,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment