Tue Aug 20 16:35:06 2013

Asterisk developer's documentation


loader.c File Reference

Module Loader. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <dirent.h>
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/cdr.h"
#include "asterisk/enum.h"
#include "asterisk/http.h"
#include "asterisk/lock.h"
#include "asterisk/features.h"
#include "asterisk/dsp.h"
#include "asterisk/udptl.h"
#include "asterisk/heap.h"
#include "asterisk/app.h"
#include "asterisk/test.h"
#include <dlfcn.h>
#include "asterisk/md5.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Data Structures

struct  ast_module
struct  ast_module_user
struct  load_order
struct  load_order_entry
struct  loadupdate
struct  module_list
struct  module_user_list
struct  reload_classes
struct  reload_queue
struct  reload_queue_item
struct  updaters

Defines

#define RTLD_LOCAL   0
#define RTLD_NOW   0

Functions

struct ast_module_user__ast_module_user_add (struct ast_module *mod, struct ast_channel *chan)
void __ast_module_user_hangup_all (struct ast_module *mod)
void __ast_module_user_remove (struct ast_module *mod, struct ast_module_user *u)
static struct load_order_entryadd_to_load_order (const char *resource, struct load_order *load_order, int required)
int ast_load_resource (const char *resource_name)
 Load a module.
int ast_loader_register (int(*v)(void))
 Add a procedure to be run when modules have been updated.
int ast_loader_unregister (int(*v)(void))
 Remove a procedure to be run when modules are updated.
int ast_module_check (const char *name)
 Check if module exists.
char * ast_module_helper (const char *line, const char *word, int pos, int state, int rpos, int needsreload)
 Match modules names for the Asterisk cli.
const char * ast_module_name (const struct ast_module *mod)
 Get the name of a module.
struct ast_moduleast_module_ref (struct ast_module *mod)
void ast_module_register (const struct ast_module_info *info)
int ast_module_reload (const char *name)
 Reload asterisk modules.
void ast_module_shutdown (void)
 Run the unload() callback for all loaded modules.
void ast_module_unref (struct ast_module *mod)
void ast_module_unregister (const struct ast_module_info *info)
void ast_process_pending_reloads (void)
 Process reload requests received during startup.
int ast_unload_resource (const char *resource_name, enum ast_module_unload_mode force)
 Unload a module.
int ast_update_module_list (int(*modentry)(const char *module, const char *description, int usecnt, const char *like), const char *like)
 Ask for a list of modules, descriptions, and use counts.
void ast_update_use_count (void)
 Notify when usecount has been changed.
static struct ast_modulefind_resource (const char *resource, int do_lock)
static unsigned int inspect_module (const struct ast_module *mod)
static int key_matches (const unsigned char *key1, const unsigned char *key2)
static struct ast_moduleload_dynamic_module (const char *resource_in, unsigned int global_symbols_only, struct ast_heap *resource_heap)
int load_modules (unsigned int preload_only)
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 int load_resource_list (struct load_order *load_order, unsigned int global_symbols, int *mod_count)
static int mod_load_cmp (void *a, void *b)
static int printdigest (const unsigned char *d)
static void queue_reload_request (const char *module)
static int resource_name_match (const char *name1_in, const char *name2_in)
static enum ast_module_load_result start_resource (struct ast_module *mod)
static void unload_dynamic_module (struct ast_module *mod)
static int verify_key (const unsigned char *key)

Variables

static char buildopt_sum [33] = AST_BUILDOPT_SUM
static int do_full_reload = 0
static struct module_list embedded_module_list
static unsigned int embedding = 1
static const unsigned char expected_key []
static ast_mutex_t reloadlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static struct ast_moduleresource_being_loaded

Detailed Description

Module Loader.

Author:
Mark Spencer <markster@digium.com>
Kevin P. Fleming <kpfleming@digium.com>
Luigi Rizzo <rizzo@icir.org>
  • See ModMngMnt

Definition in file loader.c.


Define Documentation

#define RTLD_LOCAL   0

Definition at line 69 of file loader.c.

Referenced by load_dynamic_module().

#define RTLD_NOW   0

Definition at line 65 of file loader.c.

Referenced by load_dynamic_module().


Function Documentation

struct ast_module_user* __ast_module_user_add ( struct ast_module mod,
struct ast_channel chan 
) [read]

Definition at line 209 of file loader.c.

References ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_update_use_count(), ast_module_user::chan, ast_module::usecount, and ast_module::users.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and pbx_exec().

00210 {
00211    struct ast_module_user *u;
00212 
00213    u = ast_calloc(1, sizeof(*u));
00214    if (!u) {
00215       return NULL;
00216    }
00217 
00218    u->chan = chan;
00219 
00220    AST_LIST_LOCK(&mod->users);
00221    AST_LIST_INSERT_HEAD(&mod->users, u, entry);
00222    AST_LIST_UNLOCK(&mod->users);
00223 
00224    ast_atomic_fetchadd_int(&mod->usecount, +1);
00225 
00226    ast_update_use_count();
00227 
00228    return u;
00229 }

void __ast_module_user_hangup_all ( struct ast_module mod  ) 

Definition at line 254 of file loader.c.

References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_update_use_count(), ast_module_user::chan, ast_module::usecount, and ast_module::users.

Referenced by ast_unload_resource().

00255 {
00256    struct ast_module_user *u;
00257 
00258    AST_LIST_LOCK(&mod->users);
00259    while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
00260       if (u->chan) {
00261          ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
00262       }
00263       ast_atomic_fetchadd_int(&mod->usecount, -1);
00264       ast_free(u);
00265    }
00266    AST_LIST_UNLOCK(&mod->users);
00267 
00268    ast_update_use_count();
00269 }

void __ast_module_user_remove ( struct ast_module mod,
struct ast_module_user u 
)

Definition at line 231 of file loader.c.

References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_update_use_count(), ast_module::usecount, and ast_module::users.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and pbx_exec().

00232 {
00233    if (!u) {
00234       return;
00235    }
00236 
00237    AST_LIST_LOCK(&mod->users);
00238    u = AST_LIST_REMOVE(&mod->users, u, entry);
00239    AST_LIST_UNLOCK(&mod->users);
00240    if (!u) {
00241       /*
00242        * Was not in the list.  Either a bad pointer or
00243        * __ast_module_user_hangup_all() has been called.
00244        */
00245       return;
00246    }
00247 
00248    ast_atomic_fetchadd_int(&mod->usecount, -1);
00249    ast_free(u);
00250 
00251    ast_update_use_count();
00252 }

static struct load_order_entry* add_to_load_order ( const char *  resource,
struct load_order load_order,
int  required 
) [static, read]

Definition at line 952 of file loader.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, load_order_entry::required, load_order_entry::resource, and resource_name_match().

Referenced by load_modules().

00953 {
00954    struct load_order_entry *order;
00955 
00956    AST_LIST_TRAVERSE(load_order, order, entry) {
00957       if (!resource_name_match(order->resource, resource)) {
00958          /* Make sure we have the proper setting for the required field 
00959             (we might have both load= and required= lines in modules.conf) */
00960          order->required |= required;
00961          return NULL;
00962       }
00963    }
00964 
00965    if (!(order = ast_calloc(1, sizeof(*order))))
00966       return NULL;
00967 
00968    order->resource = ast_strdup(resource);
00969    order->required = required;
00970    AST_LIST_INSERT_TAIL(load_order, order, entry);
00971 
00972    return order;
00973 }

int ast_load_resource ( const char *  resource_name  ) 

Load a module.

Parameters:
resource_name The name of the module to load.

This function is run by the PBX to load the modules. It performs all loading and initialization tasks. Basically, to load a module, just give it the name of the module and it will do the rest.

Returns:
See possible enum values for ast_module_load_result.

Definition at line 931 of file loader.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_suite_event_notify, and load_resource().

Referenced by handle_load(), load_module(), and manager_moduleload().

00932 {
00933    int res;
00934    AST_LIST_LOCK(&module_list);
00935    res = load_resource(resource_name, 0, NULL, 0);
00936    if (!res) {
00937       ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);
00938    }
00939    AST_LIST_UNLOCK(&module_list);
00940 
00941    return res;
00942 }

int ast_loader_register ( int(*)(void)  updater  ) 

Add a procedure to be run when modules have been updated.

Parameters:
updater The function to run when modules have been updated.

This function adds the given function to a linked list of functions to be run when the modules are updated.

Return values:
0 on success
-1 on failure.

Definition at line 1250 of file loader.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_malloc, and loadupdate::updater.

01251 {
01252    struct loadupdate *tmp;
01253 
01254    if (!(tmp = ast_malloc(sizeof(*tmp))))
01255       return -1;
01256 
01257    tmp->updater = v;
01258    AST_LIST_LOCK(&updaters);
01259    AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
01260    AST_LIST_UNLOCK(&updaters);
01261 
01262    return 0;
01263 }

int ast_loader_unregister ( int(*)(void)  updater  ) 

Remove a procedure to be run when modules are updated.

Parameters:
updater The updater function to unregister.

This removes the given function from the updater list.

Return values:
0 on success
-1 on failure.

Definition at line 1265 of file loader.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, and loadupdate::updater.

01266 {
01267    struct loadupdate *cur;
01268 
01269    AST_LIST_LOCK(&updaters);
01270    AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
01271       if (cur->updater == v)  {
01272          AST_LIST_REMOVE_CURRENT(entry);
01273          break;
01274       }
01275    }
01276    AST_LIST_TRAVERSE_SAFE_END;
01277    AST_LIST_UNLOCK(&updaters);
01278 
01279    return cur ? 0 : -1;
01280 }

int ast_module_check ( const char *  name  ) 

Check if module exists.

Check if module with the name given is loaded.

Definition at line 1237 of file loader.c.

References ast_strlen_zero(), and find_resource().

Referenced by ifmodule_read(), load_module(), manager_modulecheck(), and unload_module().

01238 {
01239    struct ast_module *cur;
01240 
01241    if (ast_strlen_zero(name))
01242       return 0;       /* FALSE */
01243 
01244    cur = find_resource(name, 1);
01245 
01246    return (cur != NULL);
01247 }

char* ast_module_helper ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos,
int  needsreload 
)

Match modules names for the Asterisk cli.

Parameters:
line Unused by this function, but this should be the line we are matching.
word The partial name to match.
pos The position the word we are completing is in.
state The possible match to return.
rpos The position we should be matching. This should be the same as pos.
needsreload This should be 1 if we need to reload this module and 0 otherwise. This function will only return modules that are reloadble if this is 1.
Return values:
A possible completion of the partial match.
NULL if no matches were found.

Definition at line 610 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_module::info, name, ast_module_info::reload, and ast_module::resource.

Referenced by conf_run(), handle_modlist(), handle_reload(), handle_unload(), and load_module().

00611 {
00612    struct ast_module *cur;
00613    int i, which=0, l = strlen(word);
00614    char *ret = NULL;
00615 
00616    if (pos != rpos)
00617       return NULL;
00618 
00619    AST_LIST_LOCK(&module_list);
00620    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00621       if (!strncasecmp(word, cur->resource, l) &&
00622           (cur->info->reload || !needsreload) &&
00623           ++which > state) {
00624          ret = ast_strdup(cur->resource);
00625          break;
00626       }
00627    }
00628    AST_LIST_UNLOCK(&module_list);
00629 
00630    if (!ret) {
00631       for (i=0; !ret && reload_classes[i].name; i++) {
00632          if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
00633             ret = ast_strdup(reload_classes[i].name);
00634       }
00635    }
00636 
00637    return ret;
00638 }

const char* ast_module_name ( const struct ast_module mod  ) 

Get the name of a module.

Parameters:
mod A pointer to the module.
Returns:
the name of the module
Return values:
NULL if mod or mod->info is NULL

Definition at line 104 of file loader.c.

Referenced by acf_retrieve_docs(), and ast_register_application2().

00105 {
00106    if (!mod || !mod->info) {
00107       return NULL;
00108    }
00109 
00110    return mod->info->name;
00111 }

struct ast_module* ast_module_ref ( struct ast_module mod  )  [read]
void ast_module_register ( const struct ast_module_info info  ) 

Definition at line 147 of file loader.c.

References ast_calloc, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, embedded_module_list, embedding, ast_module::info, ast_module::resource, and ast_module::users.

00148 {
00149    struct ast_module *mod;
00150 
00151    if (embedding) {
00152       if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
00153          return;
00154       strcpy(mod->resource, info->name);
00155    } else {
00156       mod = resource_being_loaded;
00157    }
00158 
00159    mod->info = info;
00160    AST_LIST_HEAD_INIT(&mod->users);
00161 
00162    /* during startup, before the loader has been initialized,
00163       there are no threads, so there is no need to take the lock
00164       on this list to manipulate it. it is also possible that it
00165       might be unsafe to use the list lock at that point... so
00166       let's avoid it altogether
00167    */
00168    if (embedding) {
00169       AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
00170    } else {
00171       AST_LIST_LOCK(&module_list);
00172       /* it is paramount that the new entry be placed at the tail of
00173          the list, otherwise the code that uses dlopen() to load
00174          dynamic modules won't be able to find out if the module it
00175          just opened was registered or failed to load
00176       */
00177       AST_LIST_INSERT_TAIL(&module_list, mod, entry);
00178       AST_LIST_UNLOCK(&module_list);
00179    }
00180 
00181    /* give the module a copy of its own handle, for later use in registrations and the like */
00182    *((struct ast_module **) &(info->self)) = mod;
00183 }

int ast_module_reload ( const char *  name  ) 

Reload asterisk modules.

Parameters:
name the name of the module to reload

This function reloads the specified module, or if no modules are specified, it will reload all loaded modules.

Note:
Modules are reloaded using their reload() functions, not unloading them and loading them again.
Returns:
0 if the specified module was not found.
Return values:
1 if the module was found but cannot be reloaded.
-1 if a reload operation is already in progress.
2 if the specfied module was found and reloaded.

Definition at line 705 of file loader.c.

References ast_config_AST_CONFIG_DIR, ast_fully_booted, ast_lastreloadtime, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_lock_path(), AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), ast_mutex_trylock, ast_mutex_unlock, ast_opt_lock_confdir, ast_test_suite_event_notify, ast_tvnow(), ast_unlock_path(), ast_verb, ast_verbose, ast_module::declined, ast_module_info::description, ast_module::flags, ast_module::info, LOG_NOTICE, LOG_WARNING, queue_reload_request(), ast_module_info::reload, ast_module::resource, resource_name_match(), and ast_module::running.

Referenced by action_reload(), action_updateconfig(), ast_process_pending_reloads(), handle_core_reload(), handle_reload(), manager_moduleload(), and monitor_sig_flags().

00706 {
00707    struct ast_module *cur;
00708    int res = 0; /* return value. 0 = not found, others, see below */
00709    int i;
00710 
00711    /* If we aren't fully booted, we just pretend we reloaded but we queue this
00712       up to run once we are booted up. */
00713    if (!ast_fully_booted) {
00714       queue_reload_request(name);
00715       return 0;
00716    }
00717 
00718    if (ast_mutex_trylock(&reloadlock)) {
00719       ast_verbose("The previous reload command didn't finish yet\n");
00720       return -1;  /* reload already in progress */
00721    }
00722    ast_lastreloadtime = ast_tvnow();
00723 
00724    if (ast_opt_lock_confdir) {
00725       int try;
00726       int res;
00727       for (try = 1, res = AST_LOCK_TIMEOUT; try < 6 && (res == AST_LOCK_TIMEOUT); try++) {
00728          res = ast_lock_path(ast_config_AST_CONFIG_DIR);
00729          if (res == AST_LOCK_TIMEOUT) {
00730             ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try);
00731          }
00732       }
00733       if (res != AST_LOCK_SUCCESS) {
00734          ast_verbose("Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR);
00735          ast_mutex_unlock(&reloadlock);
00736          return -1;
00737       }
00738    }
00739 
00740    /* Call "predefined" reload here first */
00741    for (i = 0; reload_classes[i].name; i++) {
00742       if (!name || !strcasecmp(name, reload_classes[i].name)) {
00743          if (!reload_classes[i].reload_fn()) {
00744             ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", name);
00745          }
00746          res = 2; /* found and reloaded */
00747       }
00748    }
00749 
00750    if (name && res) {
00751       if (ast_opt_lock_confdir) {
00752          ast_unlock_path(ast_config_AST_CONFIG_DIR);
00753       }
00754       ast_mutex_unlock(&reloadlock);
00755       return res;
00756    }
00757 
00758    AST_LIST_LOCK(&module_list);
00759    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00760       const struct ast_module_info *info = cur->info;
00761 
00762       if (name && resource_name_match(name, cur->resource))
00763          continue;
00764 
00765       if (!cur->flags.running || cur->flags.declined) {
00766          if (!name)
00767             continue;
00768          ast_log(LOG_NOTICE, "The module '%s' was not properly initialized.  "
00769             "Before reloading the module, you must run \"module load %s\" "
00770             "and fix whatever is preventing the module from being initialized.\n",
00771             name, name);
00772          res = 2; /* Don't report that the module was not found */
00773          break;
00774       }
00775 
00776       if (!info->reload) { /* cannot be reloaded */
00777          /* Nothing to reload, so reload is successful */
00778          ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", cur->resource);
00779          if (res < 1)   /* store result if possible */
00780             res = 1; /* 1 = no reload() method */
00781          continue;
00782       }
00783 
00784       res = 2;
00785       ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
00786       if (!info->reload()) {
00787          ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", cur->resource);
00788       }
00789    }
00790    AST_LIST_UNLOCK(&module_list);
00791 
00792    if (ast_opt_lock_confdir) {
00793       ast_unlock_path(ast_config_AST_CONFIG_DIR);
00794    }
00795    ast_mutex_unlock(&reloadlock);
00796 
00797    return res;
00798 }

void ast_module_shutdown ( void   ) 

Run the unload() callback for all loaded modules.

This function should be called when Asterisk is shutting down gracefully.

Note:
Some resources, like timers, are started up dynamically, and thus may be still in use, even if all channels are dead. We must therefore check the usecount before asking modules to unload.
If we go through the entire list without changing anything, ignore the usecounts and unload, then exit.

Definition at line 497 of file loader.c.

References AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_module::declined, ast_module::flags, free, ast_module::info, ast_module::running, ast_module_info::unload, ast_module::usecount, and ast_module::users.

Referenced by really_quit().

00498 {
00499    struct ast_module *mod;
00500    int somethingchanged = 1, final = 0;
00501 
00502    AST_LIST_LOCK(&module_list);
00503 
00504    /*!\note Some resources, like timers, are started up dynamically, and thus
00505     * may be still in use, even if all channels are dead.  We must therefore
00506     * check the usecount before asking modules to unload. */
00507    do {
00508       if (!somethingchanged) {
00509          /*!\note If we go through the entire list without changing
00510           * anything, ignore the usecounts and unload, then exit. */
00511          final = 1;
00512       }
00513 
00514       /* Reset flag before traversing the list */
00515       somethingchanged = 0;
00516 
00517       AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00518          if (!final && mod->usecount) {
00519             continue;
00520          }
00521          AST_LIST_REMOVE_CURRENT(entry);
00522          if (mod->flags.running && !mod->flags.declined && mod->info->unload) {
00523             mod->info->unload();
00524          }
00525          AST_LIST_HEAD_DESTROY(&mod->users);
00526          free(mod);
00527          somethingchanged = 1;
00528       }
00529       AST_LIST_TRAVERSE_SAFE_END;
00530    } while (somethingchanged && !final);
00531 
00532    AST_LIST_UNLOCK(&module_list);
00533 }

void ast_module_unref ( struct ast_module mod  ) 
void ast_module_unregister ( const struct ast_module_info info  ) 

Definition at line 185 of file loader.c.

References ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_module::info, and ast_module::users.

00186 {
00187    struct ast_module *mod = NULL;
00188 
00189    /* it is assumed that the users list in the module structure
00190       will already be empty, or we cannot have gotten to this
00191       point
00192    */
00193    AST_LIST_LOCK(&module_list);
00194    AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00195       if (mod->info == info) {
00196          AST_LIST_REMOVE_CURRENT(entry);
00197          break;
00198       }
00199    }
00200    AST_LIST_TRAVERSE_SAFE_END;
00201    AST_LIST_UNLOCK(&module_list);
00202 
00203    if (mod) {
00204       AST_LIST_HEAD_DESTROY(&mod->users);
00205       ast_free(mod);
00206    }
00207 }

void ast_process_pending_reloads ( void   ) 

Process reload requests received during startup.

This function requests that the loader execute the pending reload requests that were queued during server startup.

Note:
This function will do nothing if the server has not completely started up. Once called, the reload queue is emptied, and further invocations will have no affect.

Definition at line 640 of file loader.c.

References ast_free, ast_fully_booted, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_module_reload(), do_full_reload, LOG_NOTICE, and reload_queue_item::module.

Referenced by main().

00641 {
00642    struct reload_queue_item *item;
00643 
00644    if (!ast_fully_booted) {
00645       return;
00646    }
00647 
00648    AST_LIST_LOCK(&reload_queue);
00649 
00650    if (do_full_reload) {
00651       do_full_reload = 0;
00652       AST_LIST_UNLOCK(&reload_queue);
00653       ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
00654       ast_module_reload(NULL);
00655       return;
00656    }
00657 
00658    while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00659       ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
00660       ast_module_reload(item->module);
00661       ast_free(item);
00662    }
00663 
00664    AST_LIST_UNLOCK(&reload_queue);
00665 }

int ast_unload_resource ( const char *  resource_name,
enum  ast_module_unload_mode 
)

Unload a module.

Parameters:
resource_name The name of the module to unload.
ast_module_unload_mode The force flag. This should be set using one of the AST_FORCE flags.

This function unloads a module. It will only unload modules that are not in use (usecount not zero), unless AST_FORCE_FIRM or AST_FORCE_HARD is specified. Setting AST_FORCE_FIRM or AST_FORCE_HARD will unload the module regardless of consequences (NOT RECOMMENDED).

Return values:
0 on success.
-1 on error.

Definition at line 535 of file loader.c.

References __ast_module_user_hangup_all(), AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_test_suite_event_notify, ast_update_use_count(), ast_module::declined, find_resource(), ast_module::flags, ast_module::info, ast_module::lib, LOG_WARNING, ast_module_info::restore_globals, ast_module::running, ast_module_info::unload, unload_dynamic_module(), and ast_module::usecount.

Referenced by handle_unload(), manager_moduleload(), and unload_module().

00536 {
00537    struct ast_module *mod;
00538    int res = -1;
00539    int error = 0;
00540 
00541    AST_LIST_LOCK(&module_list);
00542 
00543    if (!(mod = find_resource(resource_name, 0))) {
00544       AST_LIST_UNLOCK(&module_list);
00545       ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
00546       return -1;
00547    }
00548 
00549    if (!mod->flags.running || mod->flags.declined) {
00550       ast_log(LOG_WARNING, "Unload failed, '%s' is not loaded.\n", resource_name);
00551       error = 1;
00552    }
00553 
00554    if (!error && (mod->usecount > 0)) {
00555       if (force)
00556          ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
00557             resource_name, mod->usecount);
00558       else {
00559          ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
00560             mod->usecount);
00561          error = 1;
00562       }
00563    }
00564 
00565    if (!error) {
00566       /* Request any channels attached to the module to hangup. */
00567       __ast_module_user_hangup_all(mod);
00568 
00569       res = mod->info->unload();
00570       if (res) {
00571          ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
00572          if (force <= AST_FORCE_FIRM) {
00573             error = 1;
00574          } else {
00575             ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
00576          }
00577       }
00578 
00579       if (!error) {
00580          /*
00581           * Request hangup on any channels that managed to get attached
00582           * while we called the module unload function.
00583           */
00584          __ast_module_user_hangup_all(mod);
00585          sched_yield();
00586       }
00587    }
00588 
00589    if (!error)
00590       mod->flags.running = mod->flags.declined = 0;
00591 
00592    AST_LIST_UNLOCK(&module_list);
00593 
00594    if (!error && !mod->lib && mod->info && mod->info->restore_globals)
00595       mod->info->restore_globals();
00596 
00597 #ifdef LOADABLE_MODULES
00598    if (!error) {
00599       unload_dynamic_module(mod);
00600       ast_test_suite_event_notify("MODULE_UNLOAD", "Message: %s", resource_name);
00601    }
00602 #endif
00603 
00604    if (!error)
00605       ast_update_use_count();
00606 
00607    return res;
00608 }

int ast_update_module_list ( int(*)(const char *module, const char *description, int usecnt, const char *like)  modentry,
const char *  like 
)

Ask for a list of modules, descriptions, and use counts.

Parameters:
modentry A callback to an updater function.
like For each of the modules loaded, modentry will be executed with the resource, description, and usecount values of each particular module.
Returns:
the number of modules loaded

Definition at line 1216 of file loader.c.

References AST_LIST_TRAVERSE, AST_LIST_TRYLOCK, AST_LIST_UNLOCK, ast_module_info::description, ast_module::info, ast_module::resource, and ast_module::usecount.

Referenced by ast_var_Modules(), and handle_modlist().

01218 {
01219    struct ast_module *cur;
01220    int unlock = -1;
01221    int total_mod_loaded = 0;
01222 
01223    if (AST_LIST_TRYLOCK(&module_list))
01224       unlock = 0;
01225  
01226    AST_LIST_TRAVERSE(&module_list, cur, entry) {
01227       total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
01228    }
01229 
01230    if (unlock)
01231       AST_LIST_UNLOCK(&module_list);
01232 
01233    return total_mod_loaded;
01234 }

void ast_update_use_count ( void   ) 

Notify when usecount has been changed.

This function calulates use counts and notifies anyone trying to keep track of them. It should be called whenever your module's usecount changes.

Note:
The ast_module_user_* functions take care of calling this function for you.

Definition at line 1204 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and loadupdate::updater.

Referenced by __ast_module_user_add(), __ast_module_user_hangup_all(), __ast_module_user_remove(), ast_module_ref(), ast_module_unref(), ast_unload_resource(), handle_request_do(), oh323_request(), sip_request_call(), start_resource(), and unistim_new().

01205 {
01206    /* Notify any module monitors that the use count for a
01207       resource has changed */
01208    struct loadupdate *m;
01209 
01210    AST_LIST_LOCK(&updaters);
01211    AST_LIST_TRAVERSE(&updaters, m, entry)
01212       m->updater();
01213    AST_LIST_UNLOCK(&updaters);
01214 }

static struct ast_module* find_resource ( const char *  resource,
int  do_lock 
) [static, read]

Definition at line 356 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_module::resource, and resource_name_match().

Referenced by ast_module_check(), ast_unload_resource(), load_dynamic_module(), load_modules(), and load_resource().

00357 {
00358    struct ast_module *cur;
00359 
00360    if (do_lock)
00361       AST_LIST_LOCK(&module_list);
00362 
00363    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00364       if (!resource_name_match(resource, cur->resource))
00365          break;
00366    }
00367 
00368    if (do_lock)
00369       AST_LIST_UNLOCK(&module_list);
00370 
00371    return cur;
00372 }

static unsigned int inspect_module ( const struct ast_module mod  )  [static]

Definition at line 800 of file loader.c.

References ast_log(), ast_strlen_zero(), buildopt_sum, ast_module_info::buildopt_sum, ast_module_info::description, ast_module::info, ast_module_info::key, LOG_WARNING, ast_module::resource, and verify_key().

Referenced by load_resource().

00801 {
00802    if (!mod->info->description) {
00803       ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
00804       return 1;
00805    }
00806 
00807    if (!mod->info->key) {
00808       ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
00809       return 1;
00810    }
00811 
00812    if (verify_key((unsigned char *) mod->info->key)) {
00813       ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
00814       return 1;
00815    }
00816 
00817    if (!ast_strlen_zero(mod->info->buildopt_sum) &&
00818        strcmp(buildopt_sum, mod->info->buildopt_sum)) {
00819       ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
00820       ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
00821       return 1;
00822    }
00823 
00824    return 0;
00825 }

static int key_matches ( const unsigned char *  key1,
const unsigned char *  key2 
) [static]

Definition at line 309 of file loader.c.

Referenced by verify_key().

00310 {
00311    int x;
00312 
00313    for (x = 0; x < 16; x++) {
00314       if (key1[x] != key2[x])
00315          return 0;
00316    }
00317 
00318    return 1;
00319 }

static struct ast_module* load_dynamic_module ( const char *  resource_in,
unsigned int  global_symbols_only,
struct ast_heap resource_heap 
) [static, read]

Definition at line 389 of file loader.c.

References ast_calloc, ast_config_AST_MODULE_DIR, ast_free, AST_LIST_LAST, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, ast_strdupa, ast_strip(), ast_strlen_zero(), ast_test_flag, find_resource(), ast_module::info, ast_module::lib, load_resource(), LOG_WARNING, ast_module_info::nonoptreq, ast_module::resource, resource_being_loaded, RTLD_LOCAL, and RTLD_NOW.

Referenced by load_resource().

00390 {
00391    char fn[PATH_MAX] = "";
00392    void *lib = NULL;
00393    struct ast_module *mod;
00394    unsigned int wants_global;
00395    int space;  /* room needed for the descriptor */
00396    int missing_so = 0;
00397 
00398    space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
00399    if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
00400       missing_so = 1;
00401       space += 3; /* room for the extra ".so" */
00402    }
00403 
00404    snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
00405 
00406    /* make a first load of the module in 'quiet' mode... don't try to resolve
00407       any symbols, and don't export any symbols. this will allow us to peek into
00408       the module's info block (if available) to see what flags it has set */
00409 
00410    resource_being_loaded = ast_calloc(1, space);
00411    if (!resource_being_loaded)
00412       return NULL;
00413    strcpy(resource_being_loaded->resource, resource_in);
00414    if (missing_so)
00415       strcat(resource_being_loaded->resource, ".so");
00416 
00417    if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
00418       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
00419       ast_free(resource_being_loaded);
00420       return NULL;
00421    }
00422 
00423    /* the dlopen() succeeded, let's find out if the module
00424       registered itself */
00425    /* note that this will only work properly as long as
00426       ast_module_register() (which is called by the module's
00427       constructor) places the new module at the tail of the
00428       module_list
00429    */
00430    if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
00431       ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
00432       /* no, it did not, so close it and return */
00433       while (!dlclose(lib));
00434       /* note that the module's destructor will call ast_module_unregister(),
00435          which will free the structure we allocated in resource_being_loaded */
00436       return NULL;
00437    }
00438 
00439    wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
00440 
00441    /* if we are being asked only to load modules that provide global symbols,
00442       and this one does not, then close it and return */
00443    if (global_symbols_only && !wants_global) {
00444       while (!dlclose(lib));
00445       return NULL;
00446    }
00447 
00448    /* This section is a workaround for a gcc 4.1 bug that has already been
00449     * fixed in later versions.  Unfortunately, some distributions, such as
00450     * RHEL/CentOS 5, distribute gcc 4.1, so we're stuck with having to deal
00451     * with this issue.  This basically ensures that optional_api modules are
00452     * loaded before any module which requires their functionality. */
00453 #if !defined(HAVE_ATTRIBUTE_weak_import) && !defined(HAVE_ATTRIBUTE_weakref)
00454    if (!ast_strlen_zero(mod->info->nonoptreq)) {
00455       /* Force any required dependencies to load */
00456       char *each, *required_resource = ast_strdupa(mod->info->nonoptreq);
00457       while ((each = strsep(&required_resource, ","))) {
00458          struct ast_module *dependency;
00459          each = ast_strip(each);
00460          dependency = find_resource(each, 0);
00461          /* Is it already loaded? */
00462          if (!dependency) {
00463             load_resource(each, global_symbols_only, resource_heap, 1);
00464          }
00465       }
00466    }
00467 #endif
00468 
00469    while (!dlclose(lib));
00470    resource_being_loaded = NULL;
00471 
00472    /* start the load process again */
00473    resource_being_loaded = ast_calloc(1, space);
00474    if (!resource_being_loaded)
00475       return NULL;
00476    strcpy(resource_being_loaded->resource, resource_in);
00477    if (missing_so)
00478       strcat(resource_being_loaded->resource, ".so");
00479 
00480    if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
00481       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
00482       ast_free(resource_being_loaded);
00483       return NULL;
00484    }
00485 
00486    /* since the module was successfully opened, and it registered itself
00487       the previous time we did that, we're going to assume it worked this
00488       time too :) */
00489 
00490    AST_LIST_LAST(&module_list)->lib = lib;
00491    resource_being_loaded = NULL;
00492 
00493    return AST_LIST_LAST(&module_list);
00494 }

int load_modules ( unsigned  int  ) 

Provided by loader.c

Definition at line 1054 of file loader.c.

References add_to_load_order(), ast_config_AST_MODULE_DIR, ast_config_destroy(), ast_config_load2(), ast_debug, ast_free, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), AST_MODULE_CONFIG, ast_opt_quiet, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, embedded_module_list, embedding, EVENT_FLAG_SYSTEM, find_resource(), module_list::first, ast_module::flags, module_list::last, ast_module::lib, load_resource_list(), LOG_NOTICE, LOG_WARNING, manager_event, ast_variable::name, ast_variable::next, load_order_entry::resource, ast_module::resource, resource_name_match(), ast_module::running, and ast_variable::value.

Referenced by main().

01055 {
01056    struct ast_config *cfg;
01057    struct ast_module *mod;
01058    struct load_order_entry *order;
01059    struct ast_variable *v;
01060    unsigned int load_count;
01061    struct load_order load_order;
01062    int res = 0;
01063    struct ast_flags config_flags = { 0 };
01064    int modulecount = 0;
01065 
01066 #ifdef LOADABLE_MODULES
01067    struct dirent *dirent;
01068    DIR *dir;
01069 #endif
01070 
01071    /* all embedded modules have registered themselves by now */
01072    embedding = 0;
01073 
01074    ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
01075 
01076    AST_LIST_HEAD_INIT_NOLOCK(&load_order);
01077 
01078    AST_LIST_LOCK(&module_list);
01079 
01080    if (embedded_module_list.first) {
01081       module_list.first = embedded_module_list.first;
01082       module_list.last = embedded_module_list.last;
01083       embedded_module_list.first = NULL;
01084    }
01085 
01086    cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
01087    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01088       ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
01089       goto done;
01090    }
01091 
01092    /* first, find all the modules we have been explicitly requested to load */
01093    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
01094       if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
01095          add_to_load_order(v->value, &load_order, 0);
01096       }
01097       if (!strcasecmp(v->name, preload_only ? "preload-require" : "require")) {
01098          /* Add the module to the list and make sure it's required */
01099          add_to_load_order(v->value, &load_order, 1);
01100          ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
01101       }
01102 
01103    }
01104 
01105    /* check if 'autoload' is on */
01106    if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
01107       /* if so, first add all the embedded modules that are not already running to the load order */
01108       AST_LIST_TRAVERSE(&module_list, mod, entry) {
01109          /* if it's not embedded, skip it */
01110          if (mod->lib)
01111             continue;
01112 
01113          if (mod->flags.running)
01114             continue;
01115 
01116          add_to_load_order(mod->resource, &load_order, 0);
01117       }
01118 
01119 #ifdef LOADABLE_MODULES
01120       /* if we are allowed to load dynamic modules, scan the directory for
01121          for all available modules and add them as well */
01122       if ((dir = opendir(ast_config_AST_MODULE_DIR))) {
01123          while ((dirent = readdir(dir))) {
01124             int ld = strlen(dirent->d_name);
01125 
01126             /* Must end in .so to load it.  */
01127 
01128             if (ld < 4)
01129                continue;
01130 
01131             if (strcasecmp(dirent->d_name + ld - 3, ".so"))
01132                continue;
01133 
01134             /* if there is already a module by this name in the module_list,
01135                skip this file */
01136             if (find_resource(dirent->d_name, 0))
01137                continue;
01138 
01139             add_to_load_order(dirent->d_name, &load_order, 0);
01140          }
01141 
01142          closedir(dir);
01143       } else {
01144          if (!ast_opt_quiet)
01145             ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
01146                ast_config_AST_MODULE_DIR);
01147       }
01148 #endif
01149    }
01150 
01151    /* now scan the config for any modules we are prohibited from loading and
01152       remove them from the load order */
01153    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
01154       if (strcasecmp(v->name, "noload"))
01155          continue;
01156 
01157       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
01158          if (!resource_name_match(order->resource, v->value)) {
01159             AST_LIST_REMOVE_CURRENT(entry);
01160             ast_free(order->resource);
01161             ast_free(order);
01162          }
01163       }
01164       AST_LIST_TRAVERSE_SAFE_END;
01165    }
01166 
01167    /* we are done with the config now, all the information we need is in the
01168       load_order list */
01169    ast_config_destroy(cfg);
01170 
01171    load_count = 0;
01172    AST_LIST_TRAVERSE(&load_order, order, entry)
01173       load_count++;
01174 
01175    if (load_count)
01176       ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
01177 
01178    /* first, load only modules that provide global symbols */
01179    if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
01180       goto done;
01181    }
01182 
01183    /* now load everything else */
01184    if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
01185       goto done;
01186    }
01187 
01188 done:
01189    while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
01190       ast_free(order->resource);
01191       ast_free(order);
01192    }
01193 
01194    AST_LIST_UNLOCK(&module_list);
01195    
01196    /* Tell manager clients that are aggressive at logging in that we're done
01197       loading modules. If there's a DNS problem in chan_sip, we might not
01198       even reach this */
01199    manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
01200    
01201    return res;
01202 }

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]

loads a resource based upon resource_name. If global_symbols_only is set only modules with global symbols will be loaded.

If the ast_heap is provided (not NULL) the module is found and added to the heap without running the module's load() function. By doing this, modules added to the resource_heap can be initialized later in order by priority.

If the ast_heap is not provided, the module's load function will be executed immediately

Definition at line 877 of file loader.c.

References ast_heap_push(), ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_test_flag, ast_module_info::backup_globals, ast_module::declined, find_resource(), ast_module::flags, ast_module::info, inspect_module(), ast_module::lib, load_dynamic_module(), LOG_WARNING, ast_module::running, start_resource(), and unload_dynamic_module().

Referenced by ast_load_resource(), load_dynamic_module(), and load_resource_list().

00878 {
00879    struct ast_module *mod;
00880    enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
00881 
00882    if ((mod = find_resource(resource_name, 0))) {
00883       if (mod->flags.running) {
00884          ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
00885          return AST_MODULE_LOAD_DECLINE;
00886       }
00887       if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
00888          return AST_MODULE_LOAD_SKIP;
00889    } else {
00890 #ifdef LOADABLE_MODULES
00891       if (!(mod = load_dynamic_module(resource_name, global_symbols_only, resource_heap))) {
00892          /* don't generate a warning message during load_modules() */
00893          if (!global_symbols_only) {
00894             ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00895             return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00896          } else {
00897             return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP;
00898          }
00899       }
00900 #else
00901       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00902       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00903 #endif
00904    }
00905 
00906    if (inspect_module(mod)) {
00907       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00908 #ifdef LOADABLE_MODULES
00909       unload_dynamic_module(mod);
00910 #endif
00911       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00912    }
00913 
00914    if (!mod->lib && mod->info->backup_globals && mod->info->backup_globals()) {
00915       ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
00916       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00917    }
00918 
00919    mod->flags.declined = 0;
00920 
00921    if (resource_heap) {
00922       ast_heap_push(resource_heap, mod);
00923       res = AST_MODULE_LOAD_PRIORITY;
00924    } else {
00925       res = start_resource(mod);
00926    }
00927 
00928    return res;
00929 }

static int load_resource_list ( struct load_order load_order,
unsigned int  global_symbols,
int *  mod_count 
) [static]

loads modules in order by load_pri, updates mod_count

Returns:
-1 on failure to load module, -2 on failure to load required module, otherwise 0

Definition at line 994 of file loader.c.

References ast_free, ast_heap_create(), ast_heap_destroy(), ast_heap_pop(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, load_resource(), LOG_ERROR, mod_load_cmp(), load_order_entry::required, load_order_entry::resource, and start_resource().

Referenced by load_modules().

00995 {
00996    struct ast_heap *resource_heap;
00997    struct load_order_entry *order;
00998    struct ast_module *mod;
00999    int count = 0;
01000    int res = 0;
01001 
01002    if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
01003       return -1;
01004    }
01005 
01006    /* first, add find and add modules to heap */
01007    AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
01008       switch (load_resource(order->resource, global_symbols, resource_heap, order->required)) {
01009       case AST_MODULE_LOAD_SUCCESS:
01010       case AST_MODULE_LOAD_DECLINE:
01011          AST_LIST_REMOVE_CURRENT(entry);
01012          ast_free(order->resource);
01013          ast_free(order);
01014          break;
01015       case AST_MODULE_LOAD_FAILURE:
01016          ast_log(LOG_ERROR, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
01017          fprintf(stderr, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
01018          res = order->required ? -2 : -1;
01019          goto done;
01020       case AST_MODULE_LOAD_SKIP:
01021          break;
01022       case AST_MODULE_LOAD_PRIORITY:
01023          AST_LIST_REMOVE_CURRENT(entry);
01024          break;
01025       }
01026    }
01027    AST_LIST_TRAVERSE_SAFE_END;
01028 
01029    /* second remove modules from heap sorted by priority */
01030    while ((mod = ast_heap_pop(resource_heap))) {
01031       switch (start_resource(mod)) {
01032       case AST_MODULE_LOAD_SUCCESS:
01033          count++;
01034       case AST_MODULE_LOAD_DECLINE:
01035          break;
01036       case AST_MODULE_LOAD_FAILURE:
01037          res = -1;
01038          goto done;
01039       case AST_MODULE_LOAD_SKIP:
01040       case AST_MODULE_LOAD_PRIORITY:
01041          break;
01042       }
01043    }
01044 
01045 done:
01046    if (mod_count) {
01047       *mod_count += count;
01048    }
01049    ast_heap_destroy(resource_heap);
01050 
01051    return res;
01052 }

static int mod_load_cmp ( void *  a,
void *  b 
) [static]

Definition at line 975 of file loader.c.

References AST_MODFLAG_LOAD_ORDER, ast_test_flag, ast_module::info, and ast_module_info::load_pri.

Referenced by load_resource_list().

00976 {
00977    struct ast_module *a_mod = (struct ast_module *) a;
00978    struct ast_module *b_mod = (struct ast_module *) b;
00979    int res = -1;
00980    /* if load_pri is not set, default is 128.  Lower is better*/
00981    unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128;
00982    unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128;
00983    if (a_pri == b_pri) {
00984       res = 0;
00985    } else if (a_pri < b_pri) {
00986       res = 1;
00987    }
00988    return res;
00989 }

static int printdigest ( const unsigned char *  d  )  [static]

Definition at line 296 of file loader.c.

References ast_debug.

Referenced by verify_key().

00297 {
00298    int x, pos;
00299    char buf[256]; /* large enough so we don't have to worry */
00300 
00301    for (pos = 0, x = 0; x < 16; x++)
00302       pos += sprintf(buf + pos, " %02x", *d++);
00303 
00304    ast_debug(1, "Unexpected signature:%s\n", buf);
00305 
00306    return 0;
00307 }

static void queue_reload_request ( const char *  module  )  [static]

Definition at line 667 of file loader.c.

References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), do_full_reload, LOG_ERROR, and reload_queue_item::module.

Referenced by ast_module_reload().

00668 {
00669    struct reload_queue_item *item;
00670 
00671    AST_LIST_LOCK(&reload_queue);
00672 
00673    if (do_full_reload) {
00674       AST_LIST_UNLOCK(&reload_queue);
00675       return;
00676    }
00677 
00678    if (ast_strlen_zero(module)) {
00679       /* A full reload request (when module is NULL) wipes out any previous
00680          reload requests and causes the queue to ignore future ones */
00681       while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00682          ast_free(item);
00683       }
00684       do_full_reload = 1;
00685    } else {
00686       /* No reason to add the same module twice */
00687       AST_LIST_TRAVERSE(&reload_queue, item, entry) {
00688          if (!strcasecmp(item->module, module)) {
00689             AST_LIST_UNLOCK(&reload_queue);
00690             return;
00691          }
00692       }
00693       item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
00694       if (!item) {
00695          ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
00696          AST_LIST_UNLOCK(&reload_queue);
00697          return;
00698       }
00699       strcpy(item->module, module);
00700       AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
00701    }
00702    AST_LIST_UNLOCK(&reload_queue);
00703 }

static int resource_name_match ( const char *  name1_in,
const char *  name2_in 
) [static]

Definition at line 338 of file loader.c.

References ast_strdupa.

Referenced by add_to_load_order(), ast_module_reload(), find_resource(), and load_modules().

00339 {
00340    char *name1 = (char *) name1_in;
00341    char *name2 = (char *) name2_in;
00342 
00343    /* trim off any .so extensions */
00344    if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
00345       name1 = ast_strdupa(name1);
00346       name1[strlen(name1) - 3] = '\0';
00347    }
00348    if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
00349       name2 = ast_strdupa(name2);
00350       name2[strlen(name2) - 3] = '\0';
00351    }
00352 
00353    return strcasecmp(name1, name2);
00354 }

static enum ast_module_load_result start_resource ( struct ast_module mod  )  [static]

Definition at line 827 of file loader.c.

References ast_fully_booted, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_opt_console, ast_update_use_count(), ast_verb, ast_verbose, COLOR_BLACK, COLOR_BROWN, ast_module::declined, ast_module_info::description, ast_module::flags, ast_module::info, ast_module_info::load, option_verbose, ast_module::resource, ast_module::running, and term_color().

Referenced by load_resource(), and load_resource_list().

00828 {
00829    char tmp[256];
00830    enum ast_module_load_result res;
00831 
00832    if (mod->flags.running) {
00833       return AST_MODULE_LOAD_SUCCESS;
00834    }
00835 
00836    if (!mod->info->load) {
00837       return AST_MODULE_LOAD_FAILURE;
00838    }
00839 
00840    res = mod->info->load();
00841 
00842    switch (res) {
00843    case AST_MODULE_LOAD_SUCCESS:
00844       if (!ast_fully_booted) {
00845          ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
00846          if (ast_opt_console && !option_verbose)
00847             ast_verbose( ".");
00848       } else {
00849          ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
00850       }
00851 
00852       mod->flags.running = 1;
00853 
00854       ast_update_use_count();
00855       break;
00856    case AST_MODULE_LOAD_DECLINE:
00857       mod->flags.declined = 1;
00858       break;
00859    case AST_MODULE_LOAD_FAILURE:
00860    case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
00861    case AST_MODULE_LOAD_PRIORITY:
00862       break;
00863    }
00864 
00865    return res;
00866 }

static void unload_dynamic_module ( struct ast_module mod  )  [static]

Definition at line 375 of file loader.c.

References ast_module::lib.

Referenced by ast_unload_resource(), and load_resource().

00376 {
00377    void *lib = mod->lib;
00378 
00379    /* WARNING: the structure pointed to by mod is going to
00380       disappear when this operation succeeds, so we can't
00381       dereference it */
00382 
00383    if (lib)
00384       while (!dlclose(lib));
00385 }

static int verify_key ( const unsigned char *  key  )  [static]

Definition at line 321 of file loader.c.

References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().

Referenced by inspect_module().

00322 {
00323    struct MD5Context c;
00324    unsigned char digest[16];
00325 
00326    MD5Init(&c);
00327    MD5Update(&c, key, strlen((char *)key));
00328    MD5Final(digest, &c);
00329 
00330    if (key_matches(expected_key, digest))
00331       return 0;
00332 
00333    printdigest(digest);
00334 
00335    return -1;
00336 }


Variable Documentation

char buildopt_sum[33] = AST_BUILDOPT_SUM [static]

Definition at line 83 of file loader.c.

Referenced by inspect_module().

int do_full_reload = 0 [static]

Definition at line 135 of file loader.c.

Referenced by ast_process_pending_reloads(), and queue_reload_request().

Definition at line 119 of file loader.c.

Referenced by ast_module_register(), and load_modules().

unsigned int embedding = 1 [static]

Definition at line 85 of file loader.c.

Referenced by ast_module_register(), and load_modules().

const unsigned char expected_key[] [static]
Initial value:
{ 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
  0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 }

Definition at line 79 of file loader.c.

Referenced by verify_key().

ast_mutex_t reloadlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 128 of file loader.c.

Definition at line 143 of file loader.c.

Referenced by load_dynamic_module().


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1