Re: [Evolution-hackers] Install E-D-S backends into separate directories?



On Wed, 2011-01-05 at 16:21 +0100, Milan Crha wrote:
> Ah, I see, quite complicated. The g_type_module_register_type() says:
>    As long as any instances of the type exist, the type plugin
>    will not be unloaded.
> Whatever that means. Though if it means what I would expect from it,
> then registering unconditionally all types in eds_module_initialize()
> and "dereferencing" those special types in eds_module_shutdown() may
> cause unload of the module.

It took me awhile to understand how GTypeModule works.  I know you said
you're convinced already, but let me see if I can summarize GTypeModule
and explain the problem in detail just for posterity.

  - GTypes for dynamically loaded classes are registered permanently
    regardless of whether the type module stays loaded or is unloaded.
    That's the job of GTypeModule.

  - When you reference a dynamically loaded class, whether through
    g_object_new(), g_type_create_instance(), or g_type_class_ref(),
    the type module is loaded.  In our case, loading a type module
    invokes eds_module_initialize().  So it can be called multiple
    times, which is usually harmless if all you're doing there is
    registering types.

  - When you drop the last reference to a dynamically loaded class,
    whether through g_object_unref(), g_type_free_instance(), or
    g_type_class_unref(), the type module is unloaded.

  - When a type module is unloaded, all static variables get reset.
    That's why you have to use g_type_module_register_type() instead
    of the usual pattern of:

        static GType type = 0;

        if (type == 0)
                type = g_type_register_static (...);

        return type;


The problem in, say, e-addressbook-factory is as follows:

  - Both address book and calendar type modules are loaded because they
    all reside in the same directory.  Address book type modules remain
    loaded because we create an instance of each factory backend.
    Calendar type modules, however, are immediately unloaded.

  - Calendar type modules link to libedata-cal, but libedata-book does
    not link libedata-cal (nor do I think we want to go down that road).
    Also, ECalBackendFactory is registered statically in libedata-cal.
    Therefore when calendar type modules are unloaded, the static
    GTypeInfo data for ECalBackendFactory becomes corrupted.

  - In 2.91 this corruption doesn't cause problems because calendar type
    modules are never reloaded in e-addressbook-factory.

  - Now along comes my newfangled ESource API, where extension objects
    are created on-demand by asking for them by name.  For example:

      ldap_extension = e_source_get_extension (source, "ldap-backend");

  - ESourceExtensionClass has a "name" field which each subclass must
    set to something unique.  ESourceLDAPClass, for example, sets it to
    "ldap-backend".

  - In order for ESource to match the requested extension name to the
    appropriate class, it has to peek at the "name" field of each class,
    like so:

      class = g_type_class_ref (type);

      extension_name = class->name;
      ... do some other stuff ...

      g_type_class_unref (class);

  - That call to g_type_class_ref() causes those calendar type modules
    to be reloaded, and the aforementioned ECalBackendFactory corruption
    now manifests itself -- sometimes in the form of run time warnings
    from GType, other times e-addressbook-factory crashes.

Splitting the address book and calendar type modules into separate
install directories is the simplest way I could think of to solve the
corruption problem.


> Does the proposed change (in ESourceGroup/ESource) also mean that each
> backend should provide its own ESourceExtension when it'll need to set
> some custom attributes on an ESourceGroup/ESource? I hope not.

Yes, but I'll write them.  They're nothing more than a bunch of GObject
properties with simple get/set functions.  The marshalling of those
values to and from key files is all handled transparently by ESource.

Writing those classes is monkey work, as you like to call it.  :)




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