forked from external/yambar
plugins: only dlopen() each plugin once. dlcose() in destructor
This commit is contained in:
parent
64b77a0efc
commit
962252467f
5 changed files with 95 additions and 96 deletions
|
@ -30,6 +30,7 @@ add_executable(f00bar
|
||||||
main.c
|
main.c
|
||||||
module.c module.h
|
module.c module.h
|
||||||
particle.c particle.h
|
particle.c particle.h
|
||||||
|
plugin.c plugin.h
|
||||||
tag.c tag.h
|
tag.c tag.h
|
||||||
xcb.c xcb.h
|
xcb.c xcb.h
|
||||||
yml.c yml.h
|
yml.c yml.h
|
||||||
|
|
|
@ -3,15 +3,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
#define LOG_MODULE "config:verify"
|
#define LOG_MODULE "config:verify"
|
||||||
#define LOG_ENABLE_DBG 0
|
#define LOG_ENABLE_DBG 0
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "plugin.h"
|
||||||
#include "tllist.h"
|
#include "tllist.h"
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
@ -434,40 +429,13 @@ verify_module(keychain_t *chain, const struct yml_node *node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char path[1024];
|
const struct module_info *info = plugin_load_module(mod_name);
|
||||||
snprintf(path, sizeof(path), "./modules/lib%s.so", mod_name);
|
if (info == NULL) {
|
||||||
|
LOG_ERR(
|
||||||
void *lib = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD);
|
"%s: invalid module name: %s", conf_err_prefix(chain, node), mod_name);
|
||||||
|
|
||||||
if (lib == NULL)
|
|
||||||
lib = dlopen(path, RTLD_LOCAL | RTLD_NOW);
|
|
||||||
|
|
||||||
if (lib == NULL) {
|
|
||||||
const char *dl_error = dlerror();
|
|
||||||
if (dl_error != NULL)
|
|
||||||
LOG_ERR("%s: dlopen: %s", mod_name, dlerror());
|
|
||||||
else
|
|
||||||
LOG_ERR("%s: invalid module name: %s",
|
|
||||||
conf_err_prefix(chain, module), mod_name);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char sym[1024];
|
|
||||||
snprintf(sym, sizeof(sym), "module_%s", mod_name);
|
|
||||||
|
|
||||||
dlerror(); /* Clear previous error */
|
|
||||||
const struct module_info *info = dlsym(lib, sym);
|
|
||||||
|
|
||||||
const char *dlsym_error = dlerror();
|
|
||||||
if (dlsym_error != NULL) {
|
|
||||||
LOG_ERR("%s: dlsym: %s", mod_name, dlsym_error);
|
|
||||||
dlclose(lib);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(info != NULL);
|
|
||||||
|
|
||||||
if (!conf_verify_dict(chain_push(chain, mod_name), values,
|
if (!conf_verify_dict(chain_push(chain, mod_name), values,
|
||||||
info->attrs, info->attr_count))
|
info->attrs, info->attr_count))
|
||||||
return false;
|
return false;
|
||||||
|
@ -512,45 +480,6 @@ verify_bar_location(keychain_t *chain, const struct yml_node *node)
|
||||||
return conf_verify_enum(chain, node, (const char *[]){"top", "bottom"}, 2);
|
return conf_verify_enum(chain, node, (const char *[]){"top", "bottom"}, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
|
|
||||||
static void
|
|
||||||
find_modules(void)
|
|
||||||
{
|
|
||||||
int cwd = open(".", O_RDONLY);
|
|
||||||
assert(cwd != -1);
|
|
||||||
|
|
||||||
int modules = openat(cwd, "modules", O_RDONLY);
|
|
||||||
assert(modules != -1);
|
|
||||||
|
|
||||||
DIR *dir = fdopendir(modules);
|
|
||||||
assert(dir != NULL);
|
|
||||||
|
|
||||||
for (struct dirent *e = readdir(dir); e != NULL; e = readdir(dir)) {
|
|
||||||
const size_t len = strlen(e->d_name);
|
|
||||||
|
|
||||||
if (len <= 6) {
|
|
||||||
/* Need at least "libX.so" */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(e->d_name, "lib", 3) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (strcmp(&e->d_name[len - 3], ".so") != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char *name = malloc(len - 6 + 1);
|
|
||||||
memcpy(name, &e->d_name[3], len - 6);
|
|
||||||
name[len - 6] = '\0';
|
|
||||||
|
|
||||||
LOG_DBG("%s", name);
|
|
||||||
free(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
conf_verify_bar(const struct yml_node *bar)
|
conf_verify_bar(const struct yml_node *bar)
|
||||||
{
|
{
|
||||||
|
@ -559,10 +488,6 @@ conf_verify_bar(const struct yml_node *bar)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
|
|
||||||
find_modules();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
keychain_t chain = tll_init();
|
keychain_t chain = tll_init();
|
||||||
chain_push(&chain, "bar");
|
chain_push(&chain, "bar");
|
||||||
|
|
||||||
|
|
18
config.c
18
config.c
|
@ -5,10 +5,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
||||||
#include "decoration.h"
|
#include "decoration.h"
|
||||||
|
@ -26,6 +22,7 @@
|
||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "config-verify.h"
|
#include "config-verify.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
hex_nibble(char hex)
|
hex_nibble(char hex)
|
||||||
|
@ -444,18 +441,7 @@ conf_to_bar(const struct yml_node *bar)
|
||||||
struct yml_dict_iter m = yml_dict_iter(it.node);
|
struct yml_dict_iter m = yml_dict_iter(it.node);
|
||||||
const char *mod_name = yml_value_as_string(m.key);
|
const char *mod_name = yml_value_as_string(m.key);
|
||||||
|
|
||||||
char path[1024];
|
const struct module_info *info = plugin_load_module(mod_name);
|
||||||
snprintf(path, sizeof(path), "./modules/lib%s.so", mod_name);
|
|
||||||
|
|
||||||
void *lib = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD);
|
|
||||||
assert(lib != NULL);
|
|
||||||
|
|
||||||
char sym[1024];
|
|
||||||
snprintf(sym, sizeof(sym), "module_%s", mod_name);
|
|
||||||
|
|
||||||
const struct module_info *info = dlsym(lib, sym);
|
|
||||||
assert(info != NULL);
|
|
||||||
|
|
||||||
mods[idx] = info->from_conf(m.value, font);
|
mods[idx] = info->from_conf(m.value, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
82
plugin.c
Normal file
82
plugin.c
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#define LOG_MODULE "plugin"
|
||||||
|
#define LOG_ENABLE_DBG 0
|
||||||
|
#include "log.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "tllist.h"
|
||||||
|
|
||||||
|
struct plugin {
|
||||||
|
char *name;
|
||||||
|
void *lib;
|
||||||
|
};
|
||||||
|
|
||||||
|
static tll(struct plugin) libs = tll_init();
|
||||||
|
|
||||||
|
static void __attribute__((destructor))
|
||||||
|
fini(void)
|
||||||
|
{
|
||||||
|
tll_foreach(libs, plug) {
|
||||||
|
dlerror();
|
||||||
|
dlclose(plug->item.lib);
|
||||||
|
|
||||||
|
const char *dl_error = dlerror();
|
||||||
|
if (dl_error != NULL)
|
||||||
|
LOG_ERR("%s: dlclose(): %s", plug->item.name, dl_error);
|
||||||
|
|
||||||
|
free(plug->item.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
tll_free(libs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct module_info *
|
||||||
|
plugin_load_module(const char *name)
|
||||||
|
{
|
||||||
|
char path[128];
|
||||||
|
snprintf(path, sizeof(path), "./modules/lib%s.so", name);
|
||||||
|
|
||||||
|
void *lib = NULL;
|
||||||
|
|
||||||
|
/* Have we already loaded it? */
|
||||||
|
tll_foreach(libs, plug) {
|
||||||
|
if (strcmp(plug->item.name, name) == 0) {
|
||||||
|
lib = plug->item.lib;
|
||||||
|
LOG_DBG("%s already loaded: %p", name, lib);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lib == NULL) {
|
||||||
|
/* Not loaded - do it now */
|
||||||
|
lib = dlopen(path, RTLD_LOCAL | RTLD_NOW);
|
||||||
|
LOG_DBG("%s: dlopened to %p", name, lib);
|
||||||
|
|
||||||
|
if (lib == NULL) {
|
||||||
|
LOG_ERR("%s: dlopen: %s", name, dlerror());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tll_push_back(libs, ((struct plugin){strdup(name), lib}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: use same name in all modules */
|
||||||
|
char sym[128];
|
||||||
|
snprintf(sym, sizeof(sym), "module_%s", name);
|
||||||
|
|
||||||
|
/* TODO: cache symbol */
|
||||||
|
dlerror(); /* Clear previous error */
|
||||||
|
const struct module_info *info = dlsym(lib, sym);
|
||||||
|
|
||||||
|
const char *dlsym_error = dlerror();
|
||||||
|
if (dlsym_error != NULL) {
|
||||||
|
LOG_ERR("%s: dlsym: %s", name, dlsym_error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(info != NULL);
|
||||||
|
return info;
|
||||||
|
}
|
5
plugin.h
Normal file
5
plugin.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "module.h"
|
||||||
|
|
||||||
|
const struct module_info *plugin_load_module(const char *name);
|
Loading…
Add table
Reference in a new issue