aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-21 14:42:03 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-21 14:42:03 +0000
commit991681b5f68b5c616d3a8d62258e8e4e4976a000 (patch)
tree3ec3c767359aa30b8f37b25dc297942f74998723 /main
parent2909be4a3ec32e5612006c2ada135ad2a7e8cf5d (diff)
use a safer process for checking if a module wants to export symbols into the global namespace
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@40769 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/loader.c54
1 files changed, 32 insertions, 22 deletions
diff --git a/main/loader.c b/main/loader.c
index 25c6c3773..27a6c9b60 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -333,8 +333,8 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned
char fn[256];
void *lib;
struct ast_module *mod;
- unsigned int load_global = global_symbols_only;
char *resource = (char *) resource_in;
+ unsigned int wants_global;
if (strcasecmp(resource + strlen(resource) - 3, ".so")) {
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);
-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)))
return NULL;
strcpy(resource_being_loaded->resource, resource);
- if (load_global)
- lib = dlopen(fn, RTLD_LAZY | RTLD_GLOBAL);
- else
- lib = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
-
- if (!lib) {
+ if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
ast_log(LOG_WARNING, "%s\n", dlerror());
free(resource_being_loaded);
return NULL;
@@ -371,31 +369,43 @@ tryload:
if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
/* no, it did not, so close it and return */
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;
}
+ 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;
- mod->lib = lib;
/* if we are being asked only to load modules that provide global symbols,
and this one does not, then close it and return */
- if (load_global && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
- unload_dynamic_module(mod);
+ if (global_symbols_only && !wants_global)
return NULL;
- }
- /* if we were not asked to load _only_ modules with global symbols, but
- this module wants to provide some, then we have to close and re-open
- in global mode
- */
- if (!load_global && ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
- unload_dynamic_module(mod);
- load_global = 1;
- goto tryload;
+ /* start the load process again */
+
+ if (!(resource_being_loaded = ast_calloc(1, sizeof(*resource_being_loaded) + strlen(resource) + 1)))
+ return NULL;
+
+ strcpy(resource_being_loaded->resource, resource);
+
+ 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