@ -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 ) ) ) {