diff --git a/src/backend/interfaceregistry.c b/src/backend/interfaceregistry.c index 05e2224a1..180c2043f 100644 --- a/src/backend/interfaceregistry.c +++ b/src/backend/interfaceregistry.c @@ -106,7 +106,7 @@ lumiera_interfaceregistry_init (void) if (!lumiera_interfaceregistry) LUMIERA_DIE (ERRNO); - lumiera_pluginregistry = psplay_new (lumiera_plugin_cmp_fn, lumiera_plugin_key_fn, NULL); + lumiera_pluginregistry = psplay_new (lumiera_plugin_cmp_fn, lumiera_plugin_key_fn, lumiera_plugin_delete_fn); if (!lumiera_pluginregistry) LUMIERA_DIE (ERRNO); @@ -118,20 +118,18 @@ void lumiera_interfaceregistry_destroy (void) { TRACE (interfaceregistry); - REQUIRE (!psplay_nelements (lumiera_interfaceregistry)); - - lumiera_mutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(interfaceregistry)); - - if (lumiera_interfaceregistry) - psplay_destroy (lumiera_interfaceregistry); - lumiera_interfaceregistry = NULL; - - TODO ("provide a delete function for the psplay tree to tear it down"); - REQUIRE (psplay_nelements (lumiera_pluginregistry) == 0, "plugins still loaded at destroy"); if (lumiera_pluginregistry) psplay_delete (lumiera_pluginregistry); lumiera_pluginregistry = NULL; + + lumiera_mutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(interfaceregistry)); + + REQUIRE (!psplay_nelements (lumiera_interfaceregistry), "some interfaces still registered at shutdown"); + + if (lumiera_interfaceregistry) + psplay_destroy (lumiera_interfaceregistry); + lumiera_interfaceregistry = NULL; } diff --git a/src/backend/plugin.c b/src/backend/plugin.c index 69bac0525..23d9aeed1 100644 --- a/src/backend/plugin.c +++ b/src/backend/plugin.c @@ -362,3 +362,31 @@ lumiera_plugin_key_fn (const PSplaynode node) return ((LumieraPlugin)node)->name; } + +void +lumiera_plugin_delete_fn (PSplaynode node) +{ + LumieraPlugin self = (LumieraPlugin) node; + + ENSURE (!self->refcnt, "plugin %s still in use at shutdown", self->name); + + + const char* ext = strrchr (self->name, '.'); + + LumieraPlugintype itr = lumiera_plugin_types; + while (itr->ext) + { + if (!strcmp (itr->ext, ext)) + { + if (!self->error) + { + LUMIERA_INTERFACE_HANDLE(lumieraorg__plugin, 0) handle = + LUMIERA_INTERFACE_CAST(lumieraorg__plugin, 0) self->plugin; + lumiera_interfaceregistry_bulkremove_interfaces (handle->plugin_interfaces ()); + } + itr->lumiera_plugin_unload_fn (self); + break; + } + ++itr; + } +} diff --git a/src/backend/plugin.h b/src/backend/plugin.h index dcf9180f1..b7ccd5326 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -174,5 +174,7 @@ lumiera_plugin_cmp_fn (const void* keya, const void* keyb); const void* lumiera_plugin_key_fn (const PSplaynode node); +void +lumiera_plugin_delete_fn (PSplaynode node); #endif /* LUMIERA_PLUGIN_H */ diff --git a/src/backend/plugin_dynlib.c b/src/backend/plugin_dynlib.c index 75ce4aa89..50030843c 100644 --- a/src/backend/plugin_dynlib.c +++ b/src/backend/plugin_dynlib.c @@ -54,5 +54,7 @@ void lumiera_plugin_unload_DYNLIB (LumieraPlugin self) { TRACE (plugin); - dlclose (lumiera_plugin_handle (self)); + void* handle = lumiera_plugin_handle (self); + if (handle) + dlclose (handle); }