X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcore%2Fplugin.c;h=18ea82c77fc8475d73dfb9e4a37b8a7a693443fc;hb=7261c016072283d7dce6e4fbac52e6b9c696d015;hp=6af090bfac233eec2e51a91221e4a762ee3f02f7;hpb=72a63cfb0e65bb575889b8dbee6648cafd6a52f2;p=sysdb.git diff --git a/src/core/plugin.c b/src/core/plugin.c index 6af090b..18ea82c 100644 --- a/src/core/plugin.c +++ b/src/core/plugin.c @@ -81,9 +81,15 @@ typedef struct { sdb_plugin_ctx_t public; sdb_plugin_info_t info; + lt_dlhandle handle; + + /* The usage count differs from the object's ref count + * in that it provides higher level information about how + * the plugin is in use. */ + size_t use_cnt; } ctx_t; #define CTX_INIT { SDB_OBJECT_INIT, \ - SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT } + SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT, NULL, 0 } #define CTX(obj) ((ctx_t *)(obj)) @@ -199,6 +205,7 @@ plugin_lookup_by_name(const sdb_object_t *obj, const void *id) static void plugin_unregister_by_name(const char *plugin_name) { + sdb_object_t *obj; size_t i; struct { @@ -218,19 +225,25 @@ plugin_unregister_by_name(const char *plugin_name) sdb_llist_t *list = all_lists[i].list; while (1) { - sdb_object_t *obj = sdb_llist_remove(list, - plugin_lookup_by_name, plugin_name); - sdb_plugin_cb_t *cb = SDB_PLUGIN_CB(obj); + sdb_plugin_cb_t *cb; - if (! obj) + cb = SDB_PLUGIN_CB(sdb_llist_remove(list, + plugin_lookup_by_name, plugin_name)); + if (! cb) break; sdb_log(SDB_LOG_INFO, "core: Unregistering " - "%s callback '%s' (module %s)", type, obj->name, + "%s callback '%s' (module %s)", type, cb->super.name, cb->cb_ctx->info.plugin_name); - sdb_object_deref(obj); + sdb_object_deref(SDB_OBJ(cb)); } } + + obj = sdb_llist_remove_by_name(all_plugins, plugin_name); + if (obj->ref_cnt <= 1) + sdb_log(SDB_LOG_INFO, "core: Unloading module %s", plugin_name); + /* else: other callbacks still reference it */ + sdb_object_deref(obj); } /* plugin_unregister_by_name */ /* @@ -246,6 +259,8 @@ ctx_init(sdb_object_t *obj, va_list __attribute__((unused)) ap) ctx->public = plugin_default_ctx; ctx->info = plugin_default_info; + ctx->handle = NULL; + ctx->use_cnt = 1; return 0; } /* ctx_init */ @@ -253,6 +268,16 @@ static void ctx_destroy(sdb_object_t *obj) { ctx_t *ctx = CTX(obj); + + if (ctx->handle) { + const char *err; + lt_dlerror(); + lt_dlclose(ctx->handle); + if ((err = lt_dlerror())) + sdb_log(SDB_LOG_WARNING, "core: Failed to unload plugin %s: %s", + ctx->info.plugin_name, err); + } + plugin_info_clear(&ctx->info); } /* ctx_destroy */ @@ -390,7 +415,7 @@ plugin_add_callback(sdb_llist_t **list, const char *type, int sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) { - char real_name[name ? strlen(name) + 1 : 1]; + char base_name[name ? strlen(name) + 1 : 1]; const char *name_ptr; char *tmp; @@ -405,18 +430,25 @@ sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) if ((! name) || (! *name)) return -1; - real_name[0] = '\0'; + base_name[0] = '\0'; name_ptr = name; while ((tmp = strstr(name_ptr, "::"))) { - strncat(real_name, name_ptr, (size_t)(tmp - name_ptr)); - strcat(real_name, "/"); + strncat(base_name, name_ptr, (size_t)(tmp - name_ptr)); + strcat(base_name, "/"); name_ptr = tmp + strlen("::"); } - strcat(real_name, name_ptr); + strcat(base_name, name_ptr); + + ctx = CTX(sdb_llist_search_by_name(all_plugins, base_name)); + if (ctx) { + /* plugin already loaded */ + ++ctx->use_cnt; + return 0; + } snprintf(filename, sizeof(filename), "%s/%s.so", - PKGLIBDIR, real_name); + PKGLIBDIR, base_name); filename[sizeof(filename) - 1] = '\0'; if (access(filename, R_OK)) { @@ -440,7 +472,7 @@ sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) if (ctx_get()) sdb_log(SDB_LOG_WARNING, "core: Discarding old plugin context"); - ctx = ctx_create(real_name); + ctx = ctx_create(name); if (! ctx) { sdb_log(SDB_LOG_ERR, "core: Failed to initialize plugin context"); return -1; @@ -448,6 +480,7 @@ sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) ctx->info.plugin_name = strdup(name); ctx->info.filename = strdup(filename); + ctx->handle = lh; if (plugin_ctx) ctx->public = *plugin_ctx;