@ -515,9 +515,11 @@ static void unload_dynamic_module(struct ast_module *mod)
# endif
}
static enum ast_module_load_result load_resource ( const char * resource_name , unsigned int global_symbols_only , struct ast_heap * resource_heap , int required ) ;
static enum ast_module_load_result load_resource ( const char * resource_name , unsigned int global_symbols_only , unsigned int suppress_logging , struct ast_heap * resource_heap , int required ) ;
static struct ast_module * load_dynamic_module ( const char * resource_in , unsigned int global_symbols_only , struct ast_heap * resource_heap )
# define MODULE_LOCAL_ONLY (void *)-1
static struct ast_module * load_dynamic_module ( const char * resource_in , unsigned int global_symbols_only , unsigned int suppress_logging , struct ast_heap * resource_heap )
{
char fn [ PATH_MAX ] = " " ;
void * lib = NULL ;
@ -545,8 +547,10 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned
if ( missing_so )
strcat ( resource_being_loaded - > resource , " .so " ) ;
if ( ! ( lib = dlopen ( fn , RTLD_LAZY | RTLD_LOCAL ) ) ) {
ast_log ( LOG_WARNING , " Error loading module '%s': %s \n " , resource_in , dlerror ( ) ) ;
if ( ! ( lib = dlopen ( fn , RTLD_LAZY | RTLD_GLOBAL ) ) ) {
if ( ! suppress_logging ) {
ast_log ( LOG_WARNING , " Error loading module '%s': %s \n " , resource_in , dlerror ( ) ) ;
}
ast_free ( resource_being_loaded ) ;
return NULL ;
}
@ -573,7 +577,7 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned
and this one does not , then close it and return */
if ( global_symbols_only & & ! wants_global ) {
logged_dlclose ( resource_in , lib ) ;
return NULL ;
return MODULE_LOCAL_ONLY ;
}
logged_dlclose ( resource_in , lib ) ;
@ -1053,7 +1057,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 , int required )
static enum ast_module_load_result load_resource ( const char * resource_name , unsigned int global_symbols_only , unsigned int suppress_logging , struct ast_heap * resource_heap , int required )
{
struct ast_module * mod ;
enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS ;
@ -1067,14 +1071,15 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
return AST_MODULE_LOAD_SKIP ;
} else {
# ifdef LOADABLE_MODULES
if ( ! ( mod = load_dynamic_module ( resource_name , global_symbols_only , resource_heap ) ) ) {
/* don't generate a warning message during load_modules() */
mod = load_dynamic_module ( resource_name , global_symbols_only , suppress_logging , resource_heap ) ;
if ( mod = = MODULE_LOCAL_ONLY ) {
return AST_MODULE_LOAD_SKIP ;
}
if ( ! mod ) {
if ( ! global_symbols_only ) {
ast_log ( LOG_WARNING , " Module '%s' could not be loaded. \n " , resource_name ) ;
return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE ;
} else {
return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP ;
}
return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE ;
}
# else
ast_log ( LOG_WARNING , " Module support is not available. Module '%s' could not be loaded. \n " , resource_name ) ;
@ -1111,7 +1116,7 @@ int ast_load_resource(const char *resource_name)
{
int res ;
AST_DLLIST_LOCK ( & module_list ) ;
res = load_resource ( resource_name , 0 , NULL , 0 ) ;
res = load_resource ( resource_name , 0 , 0 , NULL , 0 ) ;
if ( ! res ) {
ast_test_suite_event_notify ( " MODULE_LOAD " , " Message: %s " , resource_name ) ;
}
@ -1168,6 +1173,8 @@ static int mod_load_cmp(void *a, void *b)
return b_pri - a_pri ;
}
AST_LIST_HEAD_NOLOCK ( load_retries , load_order_entry ) ;
/*! 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
*/
@ -1176,8 +1183,13 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
struct ast_heap * resource_heap ;
struct load_order_entry * order ;
struct ast_module * mod ;
struct load_retries load_retries ;
int count = 0 ;
int res = 0 ;
int i = 0 ;
# define LOAD_RETRIES 4
AST_LIST_HEAD_INIT_NOLOCK ( & load_retries ) ;
if ( ! ( resource_heap = ast_heap_create ( 8 , mod_load_cmp , - 1 ) ) ) {
return - 1 ;
@ -1185,21 +1197,34 @@ 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 , order - > required ) ) {
enum ast_module_load_result lres ;
/* Suppress log messages unless this is the last pass */
lres = load_resource ( order - > resource , global_symbols , 1 , resource_heap , order - > required ) ;
ast_debug ( 3 , " PASS 0: %-46s %d %d \n " , order - > resource , lres , global_symbols ) ;
switch ( lres ) {
case AST_MODULE_LOAD_SUCCESS :
/* We're supplying a heap so SUCCESS isn't possible but we still have to test for it. */
break ;
case AST_MODULE_LOAD_FAILURE :
case AST_MODULE_LOAD_DECLINE :
/*
* DECLINE or FAILURE means there was an issue with dlopen or module_register
* which might be retryable . LOAD_FAILURE only happens for required modules
* but we ' re still going to retry . We need to remove the entry from the
* load_order list and add it to the load_retries list .
*/
AST_LIST_REMOVE_CURRENT ( entry ) ;
ast_free ( order - > resource ) ;
ast_free ( order ) ;
AST_LIST_INSERT_TAIL ( & load_retries , order , entry ) ;
break ;
case AST_MODULE_LOAD_FAILURE :
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 :
/*
* SKIP means that dlopen worked but global_symbols was set and this module doesn ' t qualify .
* Leave it in load_order for the next call of load_resource_list .
*/
break ;
case AST_MODULE_LOAD_PRIORITY :
/* load_resource worked and the module was added to the priority heap */
AST_LIST_REMOVE_CURRENT ( entry ) ;
ast_free ( order - > resource ) ;
ast_free ( order ) ;
@ -1208,9 +1233,56 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
}
AST_LIST_TRAVERSE_SAFE_END ;
/* Retry the failures until the list is empty or we reach LOAD_RETRIES */
for ( i = 0 ; ! AST_LIST_EMPTY ( & load_retries ) & & i < LOAD_RETRIES ; i + + ) {
AST_LIST_TRAVERSE_SAFE_BEGIN ( & load_retries , order , entry ) {
enum ast_module_load_result lres ;
/* Suppress log messages unless this is the last pass */
lres = load_resource ( order - > resource , global_symbols , ( i < LOAD_RETRIES - 1 ) , resource_heap , order - > required ) ;
ast_debug ( 3 , " PASS %d %-46s %d %d \n " , i + 1 , order - > resource , lres , global_symbols ) ;
switch ( lres ) {
/* These are all retryable. */
case AST_MODULE_LOAD_SUCCESS :
case AST_MODULE_LOAD_DECLINE :
break ;
case AST_MODULE_LOAD_FAILURE :
/* LOAD_FAILURE only happens for required modules */
if ( i = = LOAD_RETRIES - 1 ) {
/* This was the last chance to load a required module*/
ast_log ( LOG_ERROR , " *** Failed to load module %s - Required \n " , order - > resource ) ;
fprintf ( stderr , " *** Failed to load module %s - Required \n " , order - > resource ) ;
res = - 2 ;
goto done ;
}
break ; ;
case AST_MODULE_LOAD_SKIP :
/*
* SKIP means that dlopen worked but global_symbols was set and this module
* doesn ' t qualify . Put it back in load_order for the next call of
* load_resource_list .
*/
AST_LIST_REMOVE_CURRENT ( entry ) ;
AST_LIST_INSERT_TAIL ( load_order , order , entry ) ;
break ;
case AST_MODULE_LOAD_PRIORITY :
/* load_resource worked and the module was added to the priority heap */
AST_LIST_REMOVE_CURRENT ( entry ) ;
ast_free ( order - > resource ) ;
ast_free ( order ) ;
break ;
}
}
AST_LIST_TRAVERSE_SAFE_END ;
}
/* second remove modules from heap sorted by priority */
while ( ( mod = ast_heap_pop ( resource_heap ) ) ) {
switch ( start_resource ( mod ) ) {
enum ast_module_load_result lres ;
lres = start_resource ( mod ) ;
ast_debug ( 3 , " START: %-46s %d %d \n " , mod - > resource , lres , global_symbols ) ;
switch ( lres ) {
case AST_MODULE_LOAD_SUCCESS :
count + + ;
case AST_MODULE_LOAD_DECLINE :
@ -1225,6 +1297,12 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
}
done :
while ( ( order = AST_LIST_REMOVE_HEAD ( & load_retries , entry ) ) ) {
ast_free ( order - > resource ) ;
ast_free ( order ) ;
}
if ( mod_count ) {
* mod_count + = count ;
}