mirror of
https://github.com/troglobit/finit.git
synced 2026-11-12 16:51:25 +00:00
Plugin loader fixes for dep handling and unload
- Plugins without declared name registered with full path + ext => Strip path and extension - Plugins registered with __NAME__ => strip extension - Do *not* call dlclose() from destructor, must be called by Finit Also, some minor cleanup and code simplifcation. Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
1 parent
94d41e38f8
commit
e23b62ffb7
1 file changed
+61
-36
@@ -44,6 +44,21 @@ static TAILQ_HEAD(plugin_head, plugin) plugins = TAILQ_HEAD_INITIALIZER(plugins
|
|||||||
static void check_plugin_depends(plugin_t *plugin);
|
static void check_plugin_depends(plugin_t *plugin);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static char *trim_ext(char *name)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
ptr = strstr(name, ".so");
|
||||||
|
if (!ptr) ptr = strstr(name, ".c");
|
||||||
|
if (ptr)
|
||||||
|
*ptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
int plugin_register(plugin_t *plugin)
|
int plugin_register(plugin_t *plugin)
|
||||||
{
|
{
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
@@ -56,18 +71,19 @@ int plugin_register(plugin_t *plugin)
|
|||||||
#ifndef ENABLE_STATIC
|
#ifndef ENABLE_STATIC
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
|
|
||||||
if (!dladdr(plugin, &info) || !info.dli_fname)
|
if (dladdr(plugin, &info) && info.dli_fname)
|
||||||
plugin->name = "unknown";
|
plugin->name = basename(info.dli_fname);
|
||||||
else
|
|
||||||
plugin->name = (char *)info.dli_fname;
|
|
||||||
#else
|
|
||||||
plugin->name = "unknown";
|
|
||||||
#endif
|
#endif
|
||||||
|
if (!plugin->name)
|
||||||
|
plugin->name = "unknown";
|
||||||
}
|
}
|
||||||
|
plugin->name = trim_ext(strdup(plugin->name));
|
||||||
|
|
||||||
/* Already registered? */
|
/* Already registered? */
|
||||||
if (plugin_find(plugin->name)) {
|
if (plugin_find(plugin->name)) {
|
||||||
_d("... %s already loaded.", plugin->name);
|
_d("... %s already loaded.", plugin->name);
|
||||||
|
free(plugin->name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,11 +117,8 @@ int plugin_unregister(plugin_t *plugin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unload plugin */
|
_d("%s exiting ...", plugin->name);
|
||||||
if (dlclose(plugin->handle)) {
|
free(plugin->name);
|
||||||
_e("Failed unloading %s ...", plugin->name);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
_d("Finit built statically, cannot unload %s ...", plugin->name);
|
_d("Finit built statically, cannot unload %s ...", plugin->name);
|
||||||
#endif
|
#endif
|
||||||
@@ -204,17 +217,23 @@ static void generic_io_cb(uev_t *w, void *arg, int events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Setup any I/O callbacks for plugins that use them */
|
/* Setup any I/O callbacks for plugins that use them */
|
||||||
static void init_plugins(uev_ctx_t *ctx)
|
static int init_plugins(uev_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
|
int fail = 0;
|
||||||
plugin_t *p, *tmp;
|
plugin_t *p, *tmp;
|
||||||
|
|
||||||
PLUGIN_ITERATOR(p, tmp) {
|
PLUGIN_ITERATOR(p, tmp) {
|
||||||
if (is_io_plugin(p)) {
|
if (!is_io_plugin(p))
|
||||||
_d("Initializing plugin %s for I/O", basename(p->name));
|
continue;
|
||||||
if (uev_io_init(ctx, &p->watcher, generic_io_cb, p, p->io.fd, p->io.flags))
|
|
||||||
_e("Failed setting up I/O plugin %s", basename(p->name));
|
_d("Initializing plugin %s for I/O", basename(p->name));
|
||||||
|
if (uev_io_init(ctx, &p->watcher, generic_io_cb, p, p->io.fd, p->io.flags)) {
|
||||||
|
_e("Failed setting up I/O plugin %s", basename(p->name));
|
||||||
|
fail++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ENABLE_STATIC
|
#ifndef ENABLE_STATIC
|
||||||
@@ -249,10 +268,7 @@ static int load_one(char *path, char *name)
|
|||||||
snprintf(sofile, sizeof(sofile), "%s/%s%s", path, name, noext ? ".so" : "");
|
snprintf(sofile, sizeof(sofile), "%s/%s%s", path, name, noext ? ".so" : "");
|
||||||
|
|
||||||
_d("Loading plugin %s ...", basename(sofile));
|
_d("Loading plugin %s ...", basename(sofile));
|
||||||
/* Ignore leak, we do not support unloading of plugins atm.
|
handle = dlopen(sofile, RTLD_LAZY | RTLD_LOCAL);
|
||||||
* TODO: Add handle to list of loaded plugins, dlclose() on
|
|
||||||
* plugin_unregister() */
|
|
||||||
handle = dlopen(sofile, RTLD_LAZY | RTLD_GLOBAL);
|
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
_e("Failed loading plugin %s: %s", sofile, dlerror());
|
_e("Failed loading plugin %s: %s", sofile, dlerror());
|
||||||
return 1;
|
return 1;
|
||||||
@@ -296,21 +312,20 @@ static void check_plugin_depends(plugin_t *plugin)
|
|||||||
load_one(plugpath, plugin->depends[i]);
|
load_one(plugpath, plugin->depends[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_STATIC */
|
|
||||||
|
|
||||||
int plugin_init(uev_ctx_t *ctx, char *path)
|
static int load_plugins(char *path)
|
||||||
{
|
{
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
#ifndef ENABLE_STATIC
|
DIR *dp;
|
||||||
DIR *dp = opendir(path);
|
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
|
|
||||||
if (!silent)
|
if (!silent)
|
||||||
print_desc("Loading plugins", NULL);
|
print_desc("Loading plugins", NULL);
|
||||||
|
|
||||||
|
dp = opendir(path);
|
||||||
if (!dp) {
|
if (!dp) {
|
||||||
_e("Failed, cannot open plugin directory %s: %s", path, strerror(errno));
|
_e("Failed, cannot open plugin directory %s: %s", path, strerror(errno));
|
||||||
fail = 1;
|
return 1;
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
plugpath = path;
|
plugpath = path;
|
||||||
|
|
||||||
@@ -318,25 +333,31 @@ int plugin_init(uev_ctx_t *ctx, char *path)
|
|||||||
if (entry->d_name[0] == '.')
|
if (entry->d_name[0] == '.')
|
||||||
continue; /* Skip . and .. directories */
|
continue; /* Skip . and .. directories */
|
||||||
|
|
||||||
// print_desc(" Loading plugin ", basename(plugin));
|
|
||||||
if (load_one(path, entry->d_name))
|
if (load_one(path, entry->d_name))
|
||||||
fail++;
|
fail++;
|
||||||
// print_result(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
|
|
||||||
|
return fail;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
_d("Finit built statically, not loading plugins from %s ...", path);
|
static int load_plugins(char *UNUSED(path))
|
||||||
|
{
|
||||||
if (!silent)
|
if (!silent)
|
||||||
print_desc("Initializing plugins", NULL);
|
print_desc("Initializing plugins", NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* ENABLE_STATIC */
|
#endif /* ENABLE_STATIC */
|
||||||
|
|
||||||
/* Always initialize plugins */
|
int plugin_init(uev_ctx_t *ctx, char *path)
|
||||||
init_plugins(ctx);
|
{
|
||||||
|
int fail = 1;
|
||||||
|
|
||||||
|
if (!load_plugins(path))
|
||||||
|
fail = init_plugins(ctx);
|
||||||
|
|
||||||
#ifndef ENABLE_STATIC
|
|
||||||
exit:
|
|
||||||
#endif
|
|
||||||
if (!silent)
|
if (!silent)
|
||||||
print_result(fail);
|
print_result(fail);
|
||||||
|
|
||||||
@@ -345,10 +366,14 @@ exit:
|
|||||||
|
|
||||||
void plugin_exit(void)
|
void plugin_exit(void)
|
||||||
{
|
{
|
||||||
|
#ifndef ENABLE_STATIC
|
||||||
plugin_t *p, *tmp;
|
plugin_t *p, *tmp;
|
||||||
|
|
||||||
PLUGIN_ITERATOR(p, tmp)
|
PLUGIN_ITERATOR(p, tmp) {
|
||||||
plugin_unregister(p);
|
if (dlclose(p->handle))
|
||||||
|
_e("Failed: unloading plugin %s: %s", p->name, dlerror());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in new issue
Block a user