aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-12-09 15:28:59 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-12-09 15:28:59 +0000
commit410225d9651a936e85dba001ee693664fdc5c8f4 (patch)
tree06bd373dccdd5d5e67fbd69767558f87dc4238f4 /main
parent604872d772869fbe7d78a4e21940cdca32da9429 (diff)
Set a module load priority for format modules.
A recent change to app_voicemail made it such that the module now assumes that all format modules are available while processing voicemail configuration. However, when autoloading modules, it was possible that app_voicemail was loaded before the format modules. Since format modules don't depend on anything, set a module load priority on them to ensure that they get loaded first when autoloading. This version of the patch is specific to Asterisk 1.4 and 1.6.0. These versions did not already support module load priority in the module API. This adds a trivial version of this which is just a module flag to include it in a pass before loading "everything". Thanks to mmichelson for the review! (closes issue #16412) Reported by: jiddings Tested by: russell Review: https://reviewboard.asterisk.org/r/445/ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@233841 f38db490-d61c-443f-a65b-d21fe96a405b
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))) {