use a safer process for checking if a module wants to export symbols into the global namespace

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@40769 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Kevin P. Fleming 20 years ago
parent ff74cbc116
commit 5b03b3449b

@ -333,8 +333,8 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned
char fn[256]; char fn[256];
void *lib; void *lib;
struct ast_module *mod; struct ast_module *mod;
unsigned int load_global = global_symbols_only;
char *resource = (char *) resource_in; char *resource = (char *) resource_in;
unsigned int wants_global;
if (strcasecmp(resource + strlen(resource) - 3, ".so")) { if (strcasecmp(resource + strlen(resource) - 3, ".so")) {
resource = alloca(strlen(resource_in) + 3); resource = alloca(strlen(resource_in) + 3);
@ -344,18 +344,16 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned
snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR, resource); snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR, resource);
tryload: /* make a first load of the module in 'quiet' mode... don't try to resolve
any symbols, and don't export any symbols. this will allow us to peek into
the module's info block (if available) to see what flags it has set */
if (!(resource_being_loaded = ast_calloc(1, sizeof(*resource_being_loaded) + strlen(resource) + 1))) if (!(resource_being_loaded = ast_calloc(1, sizeof(*resource_being_loaded) + strlen(resource) + 1)))
return NULL; return NULL;
strcpy(resource_being_loaded->resource, resource); strcpy(resource_being_loaded->resource, resource);
if (load_global) if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
lib = dlopen(fn, RTLD_LAZY | RTLD_GLOBAL);
else
lib = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
if (!lib) {
ast_log(LOG_WARNING, "%s\n", dlerror()); ast_log(LOG_WARNING, "%s\n", dlerror());
free(resource_being_loaded); free(resource_being_loaded);
return NULL; return NULL;
@ -371,31 +369,43 @@ tryload:
if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) { if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
/* no, it did not, so close it and return */ /* no, it did not, so close it and return */
dlclose(lib); dlclose(lib);
free(resource_being_loaded); /* note that the module's destructor will call ast_module_unregister(),
which will free the structure we allocated in resource_being_loaded */
return NULL; return NULL;
} }
wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
/* we are done with this first load, so clean up and start over */
dlclose(lib);
resource_being_loaded = NULL; resource_being_loaded = NULL;
mod->lib = lib;
/* if we are being asked only to load modules that provide global symbols, /* if we are being asked only to load modules that provide global symbols,
and this one does not, then close it and return */ and this one does not, then close it and return */
if (load_global && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) { if (global_symbols_only && !wants_global)
unload_dynamic_module(mod);
return NULL; return NULL;
}
/* if we were not asked to load _only_ modules with global symbols, but /* start the load process again */
this module wants to provide some, then we have to close and re-open
in global mode if (!(resource_being_loaded = ast_calloc(1, sizeof(*resource_being_loaded) + strlen(resource) + 1)))
*/ return NULL;
if (!load_global && ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
unload_dynamic_module(mod); strcpy(resource_being_loaded->resource, resource);
load_global = 1;
goto tryload; if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
ast_log(LOG_WARNING, "%s\n", dlerror());
free(resource_being_loaded);
return NULL;
} }
return mod; /* since the module was successfully opened, and it registered itself
the previous time we did that, we're going to assume it worked this
time too :) */
AST_LIST_LAST(&module_list)->lib = lib;
resource_being_loaded = NULL;
return AST_LIST_LAST(&module_list);
} }
#endif #endif

Loading…
Cancel
Save