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. :) _______________________________________________ evolution-hackers mailing list firstname.lastname@example.org To change your list options or unsubscribe, visit ... http://mail.gnome.org/mailman/listinfo/evolution-hackers