aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/loader.c121
1 files changed, 73 insertions, 48 deletions
diff --git a/main/loader.c b/main/loader.c
index 0772db14c..2a7d35615 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -125,6 +125,19 @@ static AST_LIST_HEAD_STATIC(reload_queue, reload_queue_item);
*/
struct ast_module *resource_being_loaded;
+/*! \brief Load modules in this order. */
+enum module_load_pass {
+ /*! \brief AST_MODFLAG_LOAD_FIRST */
+ LOAD_FIRST,
+ /*! \brief AST_MODFLAG_GLOBAL_SYMBOLS */
+ LOAD_GLOBAL_SYMBOLS,
+ /*! \brief everything that is left */
+ LOAD_ALL,
+
+ /*! \brief Must remain at the end. */
+ LOAD_DONE,
+};
+
/* XXX: should we check for duplicate resource names here? */
void ast_module_register(const struct ast_module_info *info)
@@ -348,12 +361,12 @@ static void unload_dynamic_module(struct ast_module *mod)
while (!dlclose(lib));
}
-static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only)
+static struct ast_module *load_dynamic_module(const char *resource_in, enum module_load_pass load_pass)
{
char fn[PATH_MAX] = "";
void *lib = NULL;
struct ast_module *mod;
- unsigned int wants_global;
+ unsigned int wants_global = 0, not_yet = 0;
int space; /* room needed for the descriptor */
int missing_so = 0;
@@ -398,11 +411,22 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned
return NULL;
}
- wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
+ switch (load_pass) {
+ case LOAD_FIRST:
+ not_yet = !ast_test_flag(mod->info, AST_MODFLAG_LOAD_FIRST);
+ break;
+ case LOAD_GLOBAL_SYMBOLS:
+ wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
+ not_yet = !wants_global;
+ break;
+ case LOAD_ALL:
+ break;
+ case LOAD_DONE:
+ ast_log(LOG_ERROR, "Satan just bought a snowblower! (This should never happen, btw.)\n");
+ break;
+ }
- /* if we are being asked only to load modules that provide global symbols,
- and this one does not, then close it and return */
- if (global_symbols_only && !wants_global) {
+ if (not_yet) {
while (!dlclose(lib));
return NULL;
}
@@ -709,7 +733,7 @@ static unsigned int inspect_module(const struct ast_module *mod)
return 0;
}
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
+static enum ast_module_load_result load_resource(const char *resource_name, enum module_load_pass load_pass)
{
struct ast_module *mod;
enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
@@ -720,13 +744,29 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
return AST_MODULE_LOAD_DECLINE;
}
- if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
- return AST_MODULE_LOAD_SKIP;
+
+ switch (load_pass) {
+ case LOAD_FIRST:
+ if (!ast_test_flag(mod->info, AST_MODFLAG_LOAD_FIRST)) {
+ return AST_MODULE_LOAD_SKIP;
+ }
+ break;
+ case LOAD_GLOBAL_SYMBOLS:
+ if (!ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
+ return AST_MODULE_LOAD_SKIP;
+ }
+ break;
+ case LOAD_ALL:
+ break;
+ case LOAD_DONE:
+ ast_log(LOG_ERROR, "This should never happen, -EFLAMES!\n");
+ break;
+ }
} else {
#ifdef LOADABLE_MODULES
- if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
+ if (!(mod = load_dynamic_module(resource_name, load_pass))) {
/* don't generate a warning message during load_modules() */
- if (!global_symbols_only) {
+ if (load_pass == LOAD_ALL) {
ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
return AST_MODULE_LOAD_DECLINE;
} else {
@@ -830,6 +870,7 @@ int load_modules(unsigned int preload_only)
int res = 0;
struct ast_flags config_flags = { 0 };
int modulecount = 0;
+ int load_pass;
#ifdef LOADABLE_MODULES
struct dirent *dirent;
@@ -936,45 +977,29 @@ int load_modules(unsigned int preload_only)
if (load_count)
ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
- /* first, load only modules that provide global symbols */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
- switch (load_resource(order->resource, 1)) {
- case AST_MODULE_LOAD_SUCCESS:
- modulecount++;
- case AST_MODULE_LOAD_DECLINE:
- AST_LIST_REMOVE_CURRENT(entry);
- ast_free(order->resource);
- ast_free(order);
- break;
- case AST_MODULE_LOAD_FAILURE:
- res = -1;
- goto done;
- case AST_MODULE_LOAD_SKIP:
- /* try again later */
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- /* now load everything else */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
- switch (load_resource(order->resource, 0)) {
- case AST_MODULE_LOAD_SUCCESS:
- modulecount++;
- case AST_MODULE_LOAD_DECLINE:
- AST_LIST_REMOVE_CURRENT(entry);
- ast_free(order->resource);
- ast_free(order);
- break;
- case AST_MODULE_LOAD_FAILURE:
- res = -1;
- goto done;
- case AST_MODULE_LOAD_SKIP:
- /* should not happen */
- break;
+ for (load_pass = 0; load_pass < LOAD_DONE; load_pass++) {
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
+ switch (load_resource(order->resource, load_pass)) {
+ case AST_MODULE_LOAD_SUCCESS:
+ modulecount++;
+ case AST_MODULE_LOAD_DECLINE:
+ AST_LIST_REMOVE_CURRENT(entry);
+ ast_free(order->resource);
+ ast_free(order);
+ break;
+ case AST_MODULE_LOAD_FAILURE:
+ res = -1;
+ goto done;
+ case AST_MODULE_LOAD_SKIP:
+ /*
+ * Try again later. This result is received when a module is
+ * deferred because it is not a part of the current pass.
+ */
+ break;
+ }
}
+ AST_LIST_TRAVERSE_SAFE_END;
}
- AST_LIST_TRAVERSE_SAFE_END;
done:
while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {