diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | configs/modules.conf.sample | 8 | ||||
-rw-r--r-- | main/asterisk.c | 9 | ||||
-rw-r--r-- | main/loader.c | 47 |
4 files changed, 49 insertions, 19 deletions
@@ -327,6 +327,10 @@ Miscellaneous ------------- * SendText is now implemented in chan_gtalk and chan_jingle. It will simply send XMPP text messages to the remote JID. + * Modules.conf has a new option - "require" - that marks a module as critical for + the execution of Asterisk. + If one of the required modules fail to load, Asterisk will exit with a return + code set to 2. ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2 ------------- diff --git a/configs/modules.conf.sample b/configs/modules.conf.sample index 64767be31..38e33e1f4 100644 --- a/configs/modules.conf.sample +++ b/configs/modules.conf.sample @@ -21,6 +21,14 @@ autoload=yes ; Uncomment the following if you wish to use the Speech Recognition API ;preload => res_speech.so ; +; If you want Asterisk to fail if a module does not load, then use +; the "require" keyword. Asterisk will exit with a status code of 2 +; if a required module does not load. +; +; require = chan_sip.so +; If you want you can combine with preload +; preload-require = res_odbc.so +; ; If you want, load the GTK console right away. ; noload => pbx_gtkconsole.so diff --git a/main/asterisk.c b/main/asterisk.c index ea231d40e..22bfe7e76 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -3108,6 +3108,7 @@ int main(int argc, char *argv[]) char *buf; const char *runuser = NULL, *rungroup = NULL; char *remotesock = NULL; + int moduleresult; /*!< Result from the module load subsystem */ /* Remember original args for restart */ if (argc > ARRAY_LEN(_argv) - 1) { @@ -3583,9 +3584,9 @@ int main(int argc, char *argv[]) ast_xmldoc_load_documentation(); #endif - if (load_modules(1)) { /* Load modules, pre-load only */ + if ((moduleresult = load_modules(1))) { /* Load modules, pre-load only */ printf("%s", term_quit()); - exit(1); + exit(moduleresult == -2 ? 2 : 1); } if (dnsmgr_init()) { /* Initialize the DNS manager */ @@ -3657,9 +3658,9 @@ int main(int argc, char *argv[]) exit(1); } - if (load_modules(0)) { + if ((moduleresult = load_modules(0))) { /* Load modules */ printf("%s", term_quit()); - exit(1); + exit(moduleresult == -2 ? 2 : 1); } /* loads the cli_permissoins.conf file needed to implement cli restrictions. */ diff --git a/main/loader.c b/main/loader.c index 4ab313456..198ebc929 100644 --- a/main/loader.c +++ b/main/loader.c @@ -773,7 +773,7 @@ static enum ast_module_load_result start_resource(struct ast_module *mod) * * If the ast_heap is not provided, the module's load function will be executed * immediately */ -static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap) +static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap, int required) { struct ast_module *mod; enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; @@ -791,14 +791,14 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi /* don't generate a warning message during load_modules() */ if (!global_symbols_only) { ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); - return AST_MODULE_LOAD_DECLINE; + return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; } else { - return AST_MODULE_LOAD_SKIP; + return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP; } } #else ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); - return AST_MODULE_LOAD_DECLINE; + return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; #endif } @@ -807,12 +807,12 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi #ifdef LOADABLE_MODULES unload_dynamic_module(mod); #endif - return AST_MODULE_LOAD_DECLINE; + return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; } if (!mod->lib && mod->info->backup_globals()) { ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name); - return AST_MODULE_LOAD_DECLINE; + return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; } mod->flags.declined = 0; @@ -831,7 +831,7 @@ int ast_load_resource(const char *resource_name) { int res; AST_LIST_LOCK(&module_list); - res = load_resource(resource_name, 0, NULL); + res = load_resource(resource_name, 0, NULL, 0); AST_LIST_UNLOCK(&module_list); return res; @@ -839,24 +839,31 @@ int ast_load_resource(const char *resource_name) struct load_order_entry { char *resource; + int required; AST_LIST_ENTRY(load_order_entry) entry; }; AST_LIST_HEAD_NOLOCK(load_order, load_order_entry); -static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order) +static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order, int required) { struct load_order_entry *order; AST_LIST_TRAVERSE(load_order, order, entry) { - if (!resource_name_match(order->resource, resource)) + if (!resource_name_match(order->resource, resource)) { + /* Make sure we have the proper setting for the required field + (we might have both load= and required= lines in modules.conf) */ + order->required |= required; + } return NULL; + } } if (!(order = ast_calloc(1, sizeof(*order)))) return NULL; order->resource = ast_strdup(resource); + order->required = required; AST_LIST_INSERT_TAIL(load_order, order, entry); return order; @@ -878,7 +885,9 @@ static int mod_load_cmp(void *a, void *b) return res; } -/*! loads modules in order by load_pri, updates mod_count */ +/*! loads modules in order by load_pri, updates mod_count + \return -1 on failure to load module, -2 on failure to load required module, otherwise 0 +*/ static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count) { struct ast_heap *resource_heap; @@ -893,7 +902,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global /* first, add find and add modules to heap */ AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) { - switch (load_resource(order->resource, global_symbols, resource_heap)) { + switch (load_resource(order->resource, global_symbols, resource_heap, order->required)) { case AST_MODULE_LOAD_SUCCESS: case AST_MODULE_LOAD_DECLINE: AST_LIST_REMOVE_CURRENT(entry); @@ -901,7 +910,9 @@ static int load_resource_list(struct load_order *load_order, unsigned int global ast_free(order); break; case AST_MODULE_LOAD_FAILURE: - res = -1; + ast_log(LOG_ERROR, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required"); + fprintf(stderr, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required"); + res = order->required ? -2 : -1; goto done; case AST_MODULE_LOAD_SKIP: break; @@ -978,8 +989,14 @@ int load_modules(unsigned int preload_only) /* first, find all the modules we have been explicitly requested to load */ for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { if (!strcasecmp(v->name, preload_only ? "preload" : "load")) { - add_to_load_order(v->value, &load_order); + add_to_load_order(v->value, &load_order, 0); + } + if (!strcasecmp(v->name, preload_only ? "preload-require" : "require")) { + /* Add the module to the list and make sure it's required */ + add_to_load_order(v->value, &load_order, 1); + ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name); } + } /* check if 'autoload' is on */ @@ -993,7 +1010,7 @@ int load_modules(unsigned int preload_only) if (mod->flags.running) continue; - order = add_to_load_order(mod->resource, &load_order); + order = add_to_load_order(mod->resource, &load_order, 0); } #ifdef LOADABLE_MODULES @@ -1016,7 +1033,7 @@ int load_modules(unsigned int preload_only) if (find_resource(dirent->d_name, 0)) continue; - add_to_load_order(dirent->d_name, &load_order); + add_to_load_order(dirent->d_name, &load_order, 0); } closedir(dir); |