diff --git a/doc/Changelog b/doc/Changelog index 86246ad6e..637b31368 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,9 @@ +18 May 2020: Wouter + - For PR #93: dynlibmod can handle reloads and deinit and inits again, + with dlclose and dlopen of the library again. Also for multiple + modules. Fix memory leak by not closing dlopened content. Fix + to allow one dynlibmod instance by unbound-checkconf. + 15 May 2020: Wouter - Merge PR #93: Add dynamic library support. - Fixed conflicts for PR #93 and make configure, yacc, lex. diff --git a/dynlibmod/dynlibmod.c b/dynlibmod/dynlibmod.c index 4e022a82f..6ae23e86c 100644 --- a/dynlibmod/dynlibmod.c +++ b/dynlibmod/dynlibmod.c @@ -34,6 +34,11 @@ void log_dlerror() { HMODULE open_library(const char* fname) { return LoadLibrary(fname); } + +void close_library(const char* fname, __DYNMOD handle) { + (void)fname; + (void)handle; +} #else #include #define __DYNMOD void* @@ -46,11 +51,20 @@ void log_dlerror() { void* open_library(const char* fname) { return dlopen(fname, RTLD_LAZY | RTLD_GLOBAL); } + +void close_library(const char* fname, __DYNMOD handle) { + if(!handle) return; + if(dlclose(handle) != 0) { + log_err("dlclose %s: %s", fname, strerror(errno)); + } +} #endif +/** module counter for multiple dynlib modules */ +static int dynlib_mod_count = 0; + /** dynlib module init */ int dynlibmod_init(struct module_env* env, int id) { - static int dynlib_mod_count; int dynlib_mod_idx = dynlib_mod_count++; struct config_strlist* cfg_item = env->cfg->dynlib_file; struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env)); @@ -76,6 +90,7 @@ int dynlibmod_init(struct module_env* env, int id) { } verbose(VERB_ALGO, "dynlibmod[%d]: Trying to load library %s", dynlib_mod_idx, de->fname); dynamic_library = open_library(de->fname); + de->dynamic_library = (void*)dynamic_library; if (dynamic_library == NULL) { log_dlerror(); log_err("dynlibmod[%d]: unable to load dynamic library \"%s\".", dynlib_mod_idx, de->fname); @@ -147,6 +162,8 @@ void dynlibmod_deinit(struct module_env* env, int id) { if(de == NULL) return; de->func_deinit(env, id); + close_library(de->fname, (__DYNMOD)de->dynamic_library); + dynlib_mod_count--; de->fname = NULL; free(de); } diff --git a/dynlibmod/dynlibmod.h b/dynlibmod/dynlibmod.h index 1097db1e7..c34cf0e88 100644 --- a/dynlibmod/dynlibmod.h +++ b/dynlibmod/dynlibmod.h @@ -114,6 +114,8 @@ typedef int (*inplace_cb_register_wrapped_t)(void*, enum inplace_cb_list_type, v struct dynlibmod_env { /** Dynamic library filename. */ const char* fname; + /** dynamic library handle */ + void* dynamic_library; /** Module init function */ func_init_t func_init; /** Module deinit function */ diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c index 3fc638cae..77c558981 100644 --- a/smallapp/unbound-checkconf.c +++ b/smallapp/unbound-checkconf.c @@ -569,6 +569,54 @@ morechecks(struct config_file* cfg) && strcmp(cfg->module_conf, "python dns64 iterator") != 0 && strcmp(cfg->module_conf, "python dns64 validator iterator") != 0 #endif +#ifdef WITH_DYNLIBMODULE + && strcmp(cfg->module_conf, "dynlib iterator") != 0 + && strcmp(cfg->module_conf, "dynlib respip iterator") != 0 + && strcmp(cfg->module_conf, "dynlib validator iterator") != 0 + && strcmp(cfg->module_conf, "dynlib respip validator iterator") != 0 + && strcmp(cfg->module_conf, "validator dynlib iterator") != 0 + && strcmp(cfg->module_conf, "dns64 dynlib iterator") != 0 + && strcmp(cfg->module_conf, "dns64 dynlib validator iterator") != 0 + && strcmp(cfg->module_conf, "dns64 validator dynlib iterator") != 0 + && strcmp(cfg->module_conf, "dynlib dns64 iterator") != 0 + && strcmp(cfg->module_conf, "dynlib dns64 validator iterator") != 0 + && strcmp(cfg->module_conf, "dynlib dns64 cachedb iterator") != 0 + && strcmp(cfg->module_conf, "dynlib dns64 validator cachedb iterator") != 0 + && strcmp(cfg->module_conf, "dns64 dynlib cachedb iterator") != 0 + && strcmp(cfg->module_conf, "dns64 dynlib validator cachedb iterator") != 0 + && strcmp(cfg->module_conf, "dynlib cachedb iterator") != 0 + && strcmp(cfg->module_conf, "dynlib respip cachedb iterator") != 0 + && strcmp(cfg->module_conf, "dynlib validator cachedb iterator") != 0 + && strcmp(cfg->module_conf, "dynlib respip validator cachedb iterator") != 0 + && strcmp(cfg->module_conf, "cachedb dynlib iterator") != 0 + && strcmp(cfg->module_conf, "respip cachedb dynlib iterator") != 0 + && strcmp(cfg->module_conf, "validator cachedb dynlib iterator") != 0 + && strcmp(cfg->module_conf, "respip validator cachedb dynlib iterator") != 0 + && strcmp(cfg->module_conf, "validator dynlib cachedb iterator") != 0 + && strcmp(cfg->module_conf, "respip validator dynlib cachedb iterator") != 0 + && strcmp(cfg->module_conf, "dynlib subnetcache iterator") != 0 + && strcmp(cfg->module_conf, "dynlib respip subnetcache iterator") != 0 + && strcmp(cfg->module_conf, "subnetcache dynlib iterator") != 0 + && strcmp(cfg->module_conf, "respip subnetcache dynlib iterator") != 0 + && strcmp(cfg->module_conf, "dynlib subnetcache validator iterator") != 0 + && strcmp(cfg->module_conf, "dynlib respip subnetcache validator iterator") != 0 + && strcmp(cfg->module_conf, "subnetcache dynlib validator iterator") != 0 + && strcmp(cfg->module_conf, "respip subnetcache dynlib validator iterator") != 0 + && strcmp(cfg->module_conf, "subnetcache validator dynlib iterator") != 0 + && strcmp(cfg->module_conf, "respip subnetcache validator dynlib iterator") != 0 + && strcmp(cfg->module_conf, "dynlib ipsecmod iterator") != 0 + && strcmp(cfg->module_conf, "dynlib ipsecmod respip iterator") != 0 + && strcmp(cfg->module_conf, "ipsecmod dynlib iterator") != 0 + && strcmp(cfg->module_conf, "ipsecmod dynlib respip iterator") != 0 + && strcmp(cfg->module_conf, "ipsecmod validator iterator") != 0 + && strcmp(cfg->module_conf, "ipsecmod respip validator iterator") != 0 + && strcmp(cfg->module_conf, "dynlib ipsecmod validator iterator") != 0 + && strcmp(cfg->module_conf, "dynlib ipsecmod respip validator iterator") != 0 + && strcmp(cfg->module_conf, "ipsecmod dynlib validator iterator") != 0 + && strcmp(cfg->module_conf, "ipsecmod dynlib respip validator iterator") != 0 + && strcmp(cfg->module_conf, "ipsecmod validator dynlib iterator") != 0 + && strcmp(cfg->module_conf, "ipsecmod respip validator dynlib iterator") != 0 +#endif #ifdef USE_CACHEDB && strcmp(cfg->module_conf, "validator cachedb iterator") != 0 && strcmp(cfg->module_conf, "respip validator cachedb iterator") != 0