Re: [Evolution-hackers] Regarding API breakage and lost test cases
- From: Tristan Van Berkom <tristanvb openismus com>
- To: Matthew Barnes <mbarnes redhat com>
- Cc: evolution-hackers gnome org
- Subject: Re: [Evolution-hackers] Regarding API breakage and lost test cases
- Date: Thu, 31 Jan 2013 18:25:54 +0900
On 10/06/2012 09:01 AM, Matthew Barnes wrote:
On Fri, 2012-10-05 at 22:19 +0900, Tristan Van Berkom wrote:
a.) e_source_registry_commit_source_sync() seems not exactly
very sync. I haven't looked into that in detail but
surely the registry server needs to block on something else
before sending the reply.
The issue is on the client side in ESourceRegistry. I had some pretty
nasty code at one time to deal with this but must have yanked it while
reworking the APIs.
Even after the remote method call completes, ESourceRegistry will still
have to stop and wait for an "object-added" signal from its internal
GDBusObjectManagerClient, which is running in its own isolated thread.
The "object-added" signal has the new GDBusObject needed to build the
new ESource instance. And it can't complete on just any "object-added"
signal -- it has to be the "object-added" signal corresponding to the
scratch ESource that was just submitted.
I'll see if I can restore that nastiness again in 3.7.x.
Hi again.
I see there has been an improvement on this (mentioned in
https://bugzilla.gnome.org/show_bug.cgi?id=685986, which
refers to a recent commit trying to address the problem).
I'm not sure what the solution should be exactly, but we
should discuss this a bit because the problem space is
a little bigger than just the source existing in the
client-side before e_source_registry_commit_source_sync()
returns.
While I did modify the test cases to listen to the
"source-added" signal instead of relying on commit_source_sync()
(or the added timeout which I had in place before that), there
is still an interesting race condition to solve that is
observable, but not always reproducing, with the test cases.
Take the following pseudo code for instance:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ESourceRegistry *registry = e_source_registry_new_sync (...);
ESourceBackend *backend;
ESource *scratch = e_source_new_with_uid ("test-address-book", ...);
ESource *source;
EBookClient *book;
backend = e_source_get_extension (scratch, ADDRESS_BOOK);
e_source_backend_set_backend_name (backend, "local");
e_source_registry_commit_source_sync (registry, scratch...);
g_object_unref (scratch);
/* YAY, now we successfully get the source on the client side :) */
source = e_source_registry_ref_source (registry, "test-address-book");
/* ... but the addressbook factory service might not have it yet
* ... Uh oh... race condition here !
*/
book = e_book_client_new (source, ...);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Basically, the problem is that we hit an assertion from
the data factories when creating a book or calendar.
I.e. e-data-book-factory.c:data_book_factory_open()
(or impl_BookFactory_get_book() in older versions)
goes ahead and also calls e_source_registry_ref_source(),
but we dont know that _that_ process actually has the
ESource yet.
So I guess there are 2 potential ways of addressing this problem:
a.) The call to e_source_registry_commit_source() needs to postpone
completion until _all_ connected ESourceRegistry clients also
receive the new ESource, this way we know that the addressbook
factory service actually has the ESource before trying to
create a book for it. (or that the addressbook factory has
not yet been activated, which is also safe since initially
creating the ESourceRegistry will load all the existing sources
before continuing).
b.) I could envision a sort of wait/refresh explicit call on
the ESourceRegistry.
Perhaps even using e_source_registry_ref_source() would be
good, i.e when calling e_source_registry_ref_source(), if
the source is not yet in the local cache of sources, it
could fallback on a D-Bus call to the registry server
explicitly asking for the given source by UID.
If a direct D-Bus call to the actual registry service
indicates that the source doesn't exist, then it surely
really doesn't exist and an error can be reported from
e_source_registry_ref_source().
Successful completion of the e_source_registry_commit_source()
call would ensure, that any subsequent call to
e_source_registry_ref_source() would also succeed on the
same source UID.
Actually, going with the latter alternative might be a good way
of getting rid of the rather complex operation of waiting for
the "source-added" signal before completing the
e_source_registry_commit_source() call.
Cheers,
-Tristan
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]