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_entry * | add_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_module * | ast_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_module * | find_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_module * | load_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_module * | resource_being_loaded |
Module Loader.
Definition in file loader.c.
#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().
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.
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.
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.
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.
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.
updater | The updater function to unregister. |
This removes the given function from the updater list.
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.
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. |
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.
mod | A pointer to the module. |
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().
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) | [read] |
Definition at line 1282 of file loader.c.
References ast_atomic_fetchadd_int(), ast_update_use_count(), and ast_module::usecount.
Referenced by __oh323_new(), agi_handle_command(), alsa_new(), ast_agi_register(), ast_fax_tech_register(), ast_iax2_new(), ast_rtp_instance_new(), ast_srtp_create(), ast_timer_open(), dahdi_new(), data_result_generate_node(), fax_session_new(), fax_session_reserve(), find_best_technology(), fn_wrapper(), gtalk_new(), handle_cli_file_convert(), handle_orig(), load_module(), local_alloc(), mgcp_new(), moh_alloc(), moh_files_alloc(), mute_add_audiohook(), newpvt(), oss_new(), phone_check_exception(), phone_new(), sip_handle_cc(), sip_new(), skinny_new(), and smdi_load().
01283 { 01284 if (!mod) { 01285 return NULL; 01286 } 01287 01288 ast_atomic_fetchadd_int(&mod->usecount, +1); 01289 ast_update_use_count(); 01290 01291 return mod; 01292 }
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.
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.
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.
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 | ) |
Definition at line 1294 of file loader.c.
References ast_atomic_fetchadd_int(), ast_update_use_count(), and ast_module::usecount.
Referenced by agi_handle_command(), alsa_hangup(), ast_agi_unregister(), ast_bridge_check(), ast_fax_tech_unregister(), ast_rtp_instance_new(), ast_smdi_interface_destroy(), ast_srtp_destroy(), ast_timer_close(), dahdi_destroy_channel_bynum(), dahdi_hangup(), data_result_generate_node(), destroy(), destroy_bridge(), destroy_callback(), destroy_session(), filestream_destructor(), gtalk_hangup(), handle_cli_file_convert(), handle_orig(), iax2_predestroy(), instance_destructor(), local_ast_moh_cleanup(), local_pvt_destructor(), mgcp_hangup(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_cc_monitor_destructor(), sip_hangup(), skinny_hangup(), and smart_bridge_operation().
01295 { 01296 if (!mod) { 01297 return; 01298 } 01299 01300 ast_atomic_fetchadd_int(&mod->usecount, -1); 01301 ast_update_use_count(); 01302 }
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.
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.
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).
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.
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. |
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.
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().
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
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 }
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().
struct module_list embedded_module_list [static] |
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] |
{ 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] |
struct ast_module* resource_being_loaded [static] |
Definition at line 143 of file loader.c.
Referenced by load_dynamic_module().