diff --git a/src/core/plugin.c b/src/core/plugin.c
index 45d3940ff2a36b829fd1559f51074d5b6c03c2c0..929abaee8467cf4bc7f419c324cdd7c6b46a339f 100644 (file)
--- a/src/core/plugin.c
+++ b/src/core/plugin.c
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
size_t use_cnt;
} ctx_t;
#define CTX_INIT { SDB_OBJECT_INIT, \
- SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT, 0 }
+ SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT, NULL, 0 }
#define CTX(obj) ((ctx_t *)(obj))
static void
plugin_unregister_by_name(const char *plugin_name)
{
+ sdb_object_t *obj;
size_t i;
struct {
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_search_by_name(all_plugins, plugin_name);
+ if (obj->ref_cnt <= 1)
+ sdb_llist_remove_by_name(all_plugins, plugin_name);
+ /* else: other callbacks still reference it */
+ sdb_object_deref(obj);
} /* plugin_unregister_by_name */
/*
ctx->public = plugin_default_ctx;
ctx->info = plugin_default_info;
+ ctx->handle = NULL;
ctx->use_cnt = 1;
return 0;
} /* ctx_init */
ctx_destroy(sdb_object_t *obj)
{
ctx_t *ctx = CTX(obj);
+
+ if (ctx->handle) {
+ const char *err;
+
+ sdb_log(SDB_LOG_INFO, "core: Unloading module %s",
+ ctx->info.plugin_name);
+
+ lt_dlerror();
+ lt_dlclose(ctx->handle);
+ if ((err = lt_dlerror()))
+ sdb_log(SDB_LOG_WARNING, "core: Failed to unload module %s: %s",
+ ctx->info.plugin_name, err);
+ }
+
plugin_info_clear(&ctx->info);
} /* ctx_destroy */
if (! plugin_ctx_key_initialized)
ctx_key_init();
+ sdb_object_ref(SDB_OBJ(ctx));
pthread_setspecific(plugin_ctx_key, ctx);
return ctx;
} /* ctx_create */
ctx_key_init();
old = pthread_getspecific(plugin_ctx_key);
+ if (old)
+ sdb_object_deref(SDB_OBJ(old));
+ if (new)
+ sdb_object_ref(SDB_OBJ(new));
pthread_setspecific(plugin_ctx_key, new);
return old;
} /* ctx_set */
};
static int
-plugin_add_callback(sdb_llist_t **list, const char *type,
- const char *name, void *callback, sdb_object_t *user_data)
+module_init(const char *name, lt_dlhandle lh, sdb_plugin_info_t *info)
{
- sdb_object_t *obj;
-
- if ((! name) || (! callback))
- return -1;
-
- assert(list);
-
- if (! *list)
- *list = sdb_llist_create();
- if (! *list)
- return -1;
+ int (*mod_init)(sdb_plugin_info_t *);
+ int status;
- obj = sdb_object_create(name, sdb_plugin_cb_type,
- list, type, callback, user_data);
- if (! obj)
+ mod_init = (int (*)(sdb_plugin_info_t *))lt_dlsym(lh, "sdb_module_init");
+ if (! mod_init) {
+ sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s': "
+ "could not find symbol 'sdb_module_init'", name);
return -1;
+ }
- if (sdb_llist_append(*list, obj)) {
- sdb_object_deref(obj);
+ status = mod_init(info);
+ if (status) {
+ sdb_log(SDB_LOG_ERR, "core: Failed to initialize "
+ "module '%s'", name);
+ plugin_unregister_by_name(name);
return -1;
}
-
- /* pass control to the list */
- sdb_object_deref(obj);
-
- sdb_log(SDB_LOG_INFO, "core: Registered %s callback '%s'.",
- type, name);
return 0;
-} /* plugin_add_callback */
+} /* module_init */
-/*
- * public API
- */
-
-int
-sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx)
+static int
+module_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx)
{
char base_name[name ? strlen(name) + 1 : 1];
const char *name_ptr;
char *tmp;
char filename[1024];
- ctx_t *ctx;
-
lt_dlhandle lh;
- int (*mod_init)(sdb_plugin_info_t *);
- int status;
+ ctx_t *ctx;
- if ((! name) || (! *name))
- return -1;
+ int status;
base_name[0] = '\0';
name_ptr = name;
}
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, base_name);
filename[sizeof(filename) - 1] = '\0';
ctx->info.plugin_name = strdup(name);
ctx->info.filename = strdup(filename);
+ ctx->handle = lh;
if (plugin_ctx)
ctx->public = *plugin_ctx;
- mod_init = (int (*)(sdb_plugin_info_t *))lt_dlsym(lh, "sdb_module_init");
- if (! mod_init) {
- sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s': "
- "could not find symbol 'sdb_module_init'", name);
+ if ((status = module_init(name, lh, &ctx->info))) {
sdb_object_deref(SDB_OBJ(ctx));
- return -1;
- }
-
- status = mod_init(&ctx->info);
- if (status) {
- sdb_log(SDB_LOG_ERR, "core: Failed to initialize "
- "module '%s'", name);
- plugin_unregister_by_name(ctx->info.plugin_name);
- sdb_object_deref(SDB_OBJ(ctx));
- return -1;
+ return status;
}
/* compare minor version */
name, SDB_VERSION_DECODE(ctx->info.version),
SDB_VERSION_DECODE(SDB_VERSION));
- if (! all_plugins) {
- if (! (all_plugins = sdb_llist_create())) {
- sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s': "
- "internal error while creating linked list", name);
- plugin_unregister_by_name(ctx->info.plugin_name);
- sdb_object_deref(SDB_OBJ(ctx));
- return -1;
- }
- }
-
sdb_llist_append(all_plugins, SDB_OBJ(ctx));
sdb_log(SDB_LOG_INFO, "core: Successfully loaded "
/* reset */
ctx_set(NULL);
return 0;
+} /* module_load */
+
+static int
+plugin_add_callback(sdb_llist_t **list, const char *type,
+ const char *name, void *callback, sdb_object_t *user_data)
+{
+ sdb_object_t *obj;
+
+ if ((! name) || (! callback))
+ return -1;
+
+ assert(list);
+
+ if (! *list)
+ *list = sdb_llist_create();
+ if (! *list)
+ return -1;
+
+ obj = sdb_object_create(name, sdb_plugin_cb_type,
+ list, type, callback, user_data);
+ if (! obj)
+ return -1;
+
+ if (sdb_llist_append(*list, obj)) {
+ sdb_object_deref(obj);
+ return -1;
+ }
+
+ /* pass control to the list */
+ sdb_object_deref(obj);
+
+ sdb_log(SDB_LOG_INFO, "core: Registered %s callback '%s'.",
+ type, name);
+ return 0;
+} /* plugin_add_callback */
+
+/*
+ * public API
+ */
+
+int
+sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx)
+{
+ ctx_t *ctx;
+
+ if ((! name) || (! *name))
+ return -1;
+
+ if (! all_plugins) {
+ if (! (all_plugins = sdb_llist_create())) {
+ sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s': "
+ "internal error while creating linked list", name);
+ return -1;
+ }
+ }
+
+ ctx = CTX(sdb_llist_search_by_name(all_plugins, name));
+ if (ctx) {
+ /* plugin already loaded */
+ ++ctx->use_cnt;
+ return 0;
+ }
+
+ return module_load(name, plugin_ctx);
} /* sdb_plugin_load */
int