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 void | close_lib (const char *name, void *lib) |
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 968 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().
00969 { 00970 struct load_order_entry *order; 00971 00972 AST_LIST_TRAVERSE(load_order, order, entry) { 00973 if (!resource_name_match(order->resource, resource)) { 00974 /* Make sure we have the proper setting for the required field 00975 (we might have both load= and required= lines in modules.conf) */ 00976 order->required |= required; 00977 return NULL; 00978 } 00979 } 00980 00981 if (!(order = ast_calloc(1, sizeof(*order)))) 00982 return NULL; 00983 00984 order->resource = ast_strdup(resource); 00985 order->required = required; 00986 AST_LIST_INSERT_TAIL(load_order, order, entry); 00987 00988 return order; 00989 }
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 947 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().
00948 { 00949 int res; 00950 AST_LIST_LOCK(&module_list); 00951 res = load_resource(resource_name, 0, NULL, 0); 00952 if (!res) { 00953 ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name); 00954 } 00955 AST_LIST_UNLOCK(&module_list); 00956 00957 return res; 00958 }
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 1268 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_malloc, and loadupdate::updater.
01269 { 01270 struct loadupdate *tmp; 01271 01272 if (!(tmp = ast_malloc(sizeof(*tmp)))) 01273 return -1; 01274 01275 tmp->updater = v; 01276 AST_LIST_LOCK(&updaters); 01277 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 01278 AST_LIST_UNLOCK(&updaters); 01279 01280 return 0; 01281 }
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 1283 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.
01284 { 01285 struct loadupdate *cur; 01286 01287 AST_LIST_LOCK(&updaters); 01288 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 01289 if (cur->updater == v) { 01290 AST_LIST_REMOVE_CURRENT(entry); 01291 break; 01292 } 01293 } 01294 AST_LIST_TRAVERSE_SAFE_END; 01295 AST_LIST_UNLOCK(&updaters); 01296 01297 return cur ? 0 : -1; 01298 }
int ast_module_check | ( | const char * | name | ) |
Check if module exists.
Check if module with the name given is loaded.
Definition at line 1255 of file loader.c.
References ast_strlen_zero(), and find_resource().
Referenced by ifmodule_read(), load_module(), manager_modulecheck(), and unload_module().
01256 { 01257 struct ast_module *cur; 01258 01259 if (ast_strlen_zero(name)) 01260 return 0; /* FALSE */ 01261 01262 cur = find_resource(name, 1); 01263 01264 return (cur != NULL); 01265 }
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 626 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().
00627 { 00628 struct ast_module *cur; 00629 int i, which=0, l = strlen(word); 00630 char *ret = NULL; 00631 00632 if (pos != rpos) 00633 return NULL; 00634 00635 AST_LIST_LOCK(&module_list); 00636 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00637 if (!strncasecmp(word, cur->resource, l) && 00638 (cur->info->reload || !needsreload) && 00639 ++which > state) { 00640 ret = ast_strdup(cur->resource); 00641 break; 00642 } 00643 } 00644 AST_LIST_UNLOCK(&module_list); 00645 00646 if (!ret) { 00647 for (i=0; !ret && reload_classes[i].name; i++) { 00648 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00649 ret = ast_strdup(reload_classes[i].name); 00650 } 00651 } 00652 00653 return ret; 00654 }
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(), ast_register_application2(), and unload_dynamic_module().
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) | [read] |
Definition at line 1300 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_app_exec_sub(), ast_app_expand_sub_args(), 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(), mixmonitor_exec(), 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().
01301 { 01302 if (!mod) { 01303 return NULL; 01304 } 01305 01306 ast_atomic_fetchadd_int(&mod->usecount, +1); 01307 ast_update_use_count(); 01308 01309 return mod; 01310 }
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 721 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().
00722 { 00723 struct ast_module *cur; 00724 int res = 0; /* return value. 0 = not found, others, see below */ 00725 int i; 00726 00727 /* If we aren't fully booted, we just pretend we reloaded but we queue this 00728 up to run once we are booted up. */ 00729 if (!ast_fully_booted) { 00730 queue_reload_request(name); 00731 return 0; 00732 } 00733 00734 if (ast_mutex_trylock(&reloadlock)) { 00735 ast_verbose("The previous reload command didn't finish yet\n"); 00736 return -1; /* reload already in progress */ 00737 } 00738 ast_lastreloadtime = ast_tvnow(); 00739 00740 if (ast_opt_lock_confdir) { 00741 int try; 00742 int res; 00743 for (try = 1, res = AST_LOCK_TIMEOUT; try < 6 && (res == AST_LOCK_TIMEOUT); try++) { 00744 res = ast_lock_path(ast_config_AST_CONFIG_DIR); 00745 if (res == AST_LOCK_TIMEOUT) { 00746 ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try); 00747 } 00748 } 00749 if (res != AST_LOCK_SUCCESS) { 00750 ast_verbose("Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR); 00751 ast_mutex_unlock(&reloadlock); 00752 return -1; 00753 } 00754 } 00755 00756 /* Call "predefined" reload here first */ 00757 for (i = 0; reload_classes[i].name; i++) { 00758 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00759 if (!reload_classes[i].reload_fn()) { 00760 ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", name); 00761 } 00762 res = 2; /* found and reloaded */ 00763 } 00764 } 00765 00766 if (name && res) { 00767 if (ast_opt_lock_confdir) { 00768 ast_unlock_path(ast_config_AST_CONFIG_DIR); 00769 } 00770 ast_mutex_unlock(&reloadlock); 00771 return res; 00772 } 00773 00774 AST_LIST_LOCK(&module_list); 00775 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00776 const struct ast_module_info *info = cur->info; 00777 00778 if (name && resource_name_match(name, cur->resource)) 00779 continue; 00780 00781 if (!cur->flags.running || cur->flags.declined) { 00782 if (!name) 00783 continue; 00784 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. " 00785 "Before reloading the module, you must run \"module load %s\" " 00786 "and fix whatever is preventing the module from being initialized.\n", 00787 name, name); 00788 res = 2; /* Don't report that the module was not found */ 00789 break; 00790 } 00791 00792 if (!info->reload) { /* cannot be reloaded */ 00793 /* Nothing to reload, so reload is successful */ 00794 ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", cur->resource); 00795 if (res < 1) /* store result if possible */ 00796 res = 1; /* 1 = no reload() method */ 00797 continue; 00798 } 00799 00800 res = 2; 00801 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description); 00802 if (!info->reload()) { 00803 ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", cur->resource); 00804 } 00805 } 00806 AST_LIST_UNLOCK(&module_list); 00807 00808 if (ast_opt_lock_confdir) { 00809 ast_unlock_path(ast_config_AST_CONFIG_DIR); 00810 } 00811 ast_mutex_unlock(&reloadlock); 00812 00813 return res; 00814 }
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 513 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().
00514 { 00515 struct ast_module *mod; 00516 int somethingchanged = 1, final = 0; 00517 00518 AST_LIST_LOCK(&module_list); 00519 00520 /*!\note Some resources, like timers, are started up dynamically, and thus 00521 * may be still in use, even if all channels are dead. We must therefore 00522 * check the usecount before asking modules to unload. */ 00523 do { 00524 if (!somethingchanged) { 00525 /*!\note If we go through the entire list without changing 00526 * anything, ignore the usecounts and unload, then exit. */ 00527 final = 1; 00528 } 00529 00530 /* Reset flag before traversing the list */ 00531 somethingchanged = 0; 00532 00533 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) { 00534 if (!final && mod->usecount) { 00535 continue; 00536 } 00537 AST_LIST_REMOVE_CURRENT(entry); 00538 if (mod->flags.running && !mod->flags.declined && mod->info->unload) { 00539 mod->info->unload(); 00540 } 00541 AST_LIST_HEAD_DESTROY(&mod->users); 00542 free(mod); 00543 somethingchanged = 1; 00544 } 00545 AST_LIST_TRAVERSE_SAFE_END; 00546 } while (somethingchanged && !final); 00547 00548 AST_LIST_UNLOCK(&module_list); 00549 }
void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 1312 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_app_exec_sub(), ast_app_expand_sub_args(), 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(), fax_session_new(), filestream_destructor(), gtalk_hangup(), handle_cli_file_convert(), handle_orig(), iax2_predestroy(), instance_destructor(), local_ast_moh_cleanup(), local_pvt_destructor(), mgcp_hangup(), mixmonitor_exec(), mixmonitor_thread(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_cc_monitor_destructor(), sip_hangup(), skinny_hangup(), and smart_bridge_operation().
01313 { 01314 if (!mod) { 01315 return; 01316 } 01317 01318 ast_atomic_fetchadd_int(&mod->usecount, -1); 01319 ast_update_use_count(); 01320 }
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 656 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().
00657 { 00658 struct reload_queue_item *item; 00659 00660 if (!ast_fully_booted) { 00661 return; 00662 } 00663 00664 AST_LIST_LOCK(&reload_queue); 00665 00666 if (do_full_reload) { 00667 do_full_reload = 0; 00668 AST_LIST_UNLOCK(&reload_queue); 00669 ast_log(LOG_NOTICE, "Executing deferred reload request.\n"); 00670 ast_module_reload(NULL); 00671 return; 00672 } 00673 00674 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) { 00675 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module); 00676 ast_module_reload(item->module); 00677 ast_free(item); 00678 } 00679 00680 AST_LIST_UNLOCK(&reload_queue); 00681 }
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 551 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().
00552 { 00553 struct ast_module *mod; 00554 int res = -1; 00555 int error = 0; 00556 00557 AST_LIST_LOCK(&module_list); 00558 00559 if (!(mod = find_resource(resource_name, 0))) { 00560 AST_LIST_UNLOCK(&module_list); 00561 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name); 00562 return -1; 00563 } 00564 00565 if (!mod->flags.running || mod->flags.declined) { 00566 ast_log(LOG_WARNING, "Unload failed, '%s' is not loaded.\n", resource_name); 00567 error = 1; 00568 } 00569 00570 if (!error && (mod->usecount > 0)) { 00571 if (force) 00572 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00573 resource_name, mod->usecount); 00574 else { 00575 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00576 mod->usecount); 00577 error = 1; 00578 } 00579 } 00580 00581 if (!error) { 00582 /* Request any channels attached to the module to hangup. */ 00583 __ast_module_user_hangup_all(mod); 00584 00585 res = mod->info->unload(); 00586 if (res) { 00587 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00588 if (force <= AST_FORCE_FIRM) { 00589 error = 1; 00590 } else { 00591 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00592 } 00593 } 00594 00595 if (!error) { 00596 /* 00597 * Request hangup on any channels that managed to get attached 00598 * while we called the module unload function. 00599 */ 00600 __ast_module_user_hangup_all(mod); 00601 sched_yield(); 00602 } 00603 } 00604 00605 if (!error) 00606 mod->flags.running = mod->flags.declined = 0; 00607 00608 AST_LIST_UNLOCK(&module_list); 00609 00610 if (!error && !mod->lib && mod->info && mod->info->restore_globals) 00611 mod->info->restore_globals(); 00612 00613 #ifdef LOADABLE_MODULES 00614 if (!error) { 00615 unload_dynamic_module(mod); 00616 ast_test_suite_event_notify("MODULE_UNLOAD", "Message: %s", resource_name); 00617 } 00618 #endif 00619 00620 if (!error) 00621 ast_update_use_count(); 00622 00623 return res; 00624 }
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 1234 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().
01236 { 01237 struct ast_module *cur; 01238 int unlock = -1; 01239 int total_mod_loaded = 0; 01240 01241 if (AST_LIST_TRYLOCK(&module_list)) 01242 unlock = 0; 01243 01244 AST_LIST_TRAVERSE(&module_list, cur, entry) { 01245 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 01246 } 01247 01248 if (unlock) 01249 AST_LIST_UNLOCK(&module_list); 01250 01251 return total_mod_loaded; 01252 }
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 1222 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().
01223 { 01224 /* Notify any module monitors that the use count for a 01225 resource has changed */ 01226 struct loadupdate *m; 01227 01228 AST_LIST_LOCK(&updaters); 01229 AST_LIST_TRAVERSE(&updaters, m, entry) 01230 m->updater(); 01231 AST_LIST_UNLOCK(&updaters); 01232 }
static void close_lib | ( | const char * | name, | |
void * | lib | |||
) | [static] |
Definition at line 376 of file loader.c.
References ast_log(), AST_LOG_ERROR, and S_OR.
Referenced by load_dynamic_module(), and unload_dynamic_module().
00377 { 00378 char *error; 00379 00380 if (!lib) { 00381 return; 00382 } 00383 00384 /* Clear any existing error */ 00385 dlerror(); 00386 if (dlclose(lib)) { 00387 error = dlerror(); 00388 ast_log(AST_LOG_ERROR, "Failure in dlclose for module '%s': %s\n", 00389 S_OR(name, "unknown"), S_OR(error, "Unknown error")); 00390 } 00391 }
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 816 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().
00817 { 00818 if (!mod->info->description) { 00819 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00820 return 1; 00821 } 00822 00823 if (!mod->info->key) { 00824 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00825 return 1; 00826 } 00827 00828 if (verify_key((unsigned char *) mod->info->key)) { 00829 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00830 return 1; 00831 } 00832 00833 if (!ast_strlen_zero(mod->info->buildopt_sum) && 00834 strcmp(buildopt_sum, mod->info->buildopt_sum)) { 00835 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource); 00836 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource); 00837 return 1; 00838 } 00839 00840 return 0; 00841 }
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 405 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, close_lib(), 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().
00406 { 00407 char fn[PATH_MAX] = ""; 00408 void *lib = NULL; 00409 struct ast_module *mod; 00410 unsigned int wants_global; 00411 int space; /* room needed for the descriptor */ 00412 int missing_so = 0; 00413 00414 space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1; 00415 if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) { 00416 missing_so = 1; 00417 space += 3; /* room for the extra ".so" */ 00418 } 00419 00420 snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : ""); 00421 00422 /* make a first load of the module in 'quiet' mode... don't try to resolve 00423 any symbols, and don't export any symbols. this will allow us to peek into 00424 the module's info block (if available) to see what flags it has set */ 00425 00426 resource_being_loaded = ast_calloc(1, space); 00427 if (!resource_being_loaded) 00428 return NULL; 00429 strcpy(resource_being_loaded->resource, resource_in); 00430 if (missing_so) 00431 strcat(resource_being_loaded->resource, ".so"); 00432 00433 if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) { 00434 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); 00435 ast_free(resource_being_loaded); 00436 return NULL; 00437 } 00438 00439 /* the dlopen() succeeded, let's find out if the module 00440 registered itself */ 00441 /* note that this will only work properly as long as 00442 ast_module_register() (which is called by the module's 00443 constructor) places the new module at the tail of the 00444 module_list 00445 */ 00446 if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) { 00447 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in); 00448 /* no, it did not, so close it and return */ 00449 close_lib(resource_in, lib); 00450 /* note that the module's destructor will call ast_module_unregister(), 00451 which will free the structure we allocated in resource_being_loaded */ 00452 return NULL; 00453 } 00454 00455 wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS); 00456 00457 /* if we are being asked only to load modules that provide global symbols, 00458 and this one does not, then close it and return */ 00459 if (global_symbols_only && !wants_global) { 00460 close_lib(resource_in, lib); 00461 return NULL; 00462 } 00463 00464 /* This section is a workaround for a gcc 4.1 bug that has already been 00465 * fixed in later versions. Unfortunately, some distributions, such as 00466 * RHEL/CentOS 5, distribute gcc 4.1, so we're stuck with having to deal 00467 * with this issue. This basically ensures that optional_api modules are 00468 * loaded before any module which requires their functionality. */ 00469 #if !defined(HAVE_ATTRIBUTE_weak_import) && !defined(HAVE_ATTRIBUTE_weakref) 00470 if (!ast_strlen_zero(mod->info->nonoptreq)) { 00471 /* Force any required dependencies to load */ 00472 char *each, *required_resource = ast_strdupa(mod->info->nonoptreq); 00473 while ((each = strsep(&required_resource, ","))) { 00474 struct ast_module *dependency; 00475 each = ast_strip(each); 00476 dependency = find_resource(each, 0); 00477 /* Is it already loaded? */ 00478 if (!dependency) { 00479 load_resource(each, global_symbols_only, resource_heap, 1); 00480 } 00481 } 00482 } 00483 #endif 00484 00485 close_lib(resource_in, lib); 00486 resource_being_loaded = NULL; 00487 00488 /* start the load process again */ 00489 resource_being_loaded = ast_calloc(1, space); 00490 if (!resource_being_loaded) 00491 return NULL; 00492 strcpy(resource_being_loaded->resource, resource_in); 00493 if (missing_so) 00494 strcat(resource_being_loaded->resource, ".so"); 00495 00496 if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) { 00497 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); 00498 ast_free(resource_being_loaded); 00499 return NULL; 00500 } 00501 00502 /* since the module was successfully opened, and it registered itself 00503 the previous time we did that, we're going to assume it worked this 00504 time too :) */ 00505 00506 AST_LIST_LAST(&module_list)->lib = lib; 00507 resource_being_loaded = NULL; 00508 00509 return AST_LIST_LAST(&module_list); 00510 }
int load_modules | ( | unsigned | int | ) |
Provided by loader.c
Definition at line 1072 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().
01073 { 01074 struct ast_config *cfg; 01075 struct ast_module *mod; 01076 struct load_order_entry *order; 01077 struct ast_variable *v; 01078 unsigned int load_count; 01079 struct load_order load_order; 01080 int res = 0; 01081 struct ast_flags config_flags = { 0 }; 01082 int modulecount = 0; 01083 01084 #ifdef LOADABLE_MODULES 01085 struct dirent *dirent; 01086 DIR *dir; 01087 #endif 01088 01089 /* all embedded modules have registered themselves by now */ 01090 embedding = 0; 01091 01092 ast_verb(1, "Asterisk Dynamic Loader Starting:\n"); 01093 01094 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 01095 01096 AST_LIST_LOCK(&module_list); 01097 01098 if (embedded_module_list.first) { 01099 module_list.first = embedded_module_list.first; 01100 module_list.last = embedded_module_list.last; 01101 embedded_module_list.first = NULL; 01102 } 01103 01104 cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags); 01105 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 01106 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 01107 goto done; 01108 } 01109 01110 /* first, find all the modules we have been explicitly requested to load */ 01111 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 01112 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) { 01113 add_to_load_order(v->value, &load_order, 0); 01114 } 01115 if (!strcasecmp(v->name, preload_only ? "preload-require" : "require")) { 01116 /* Add the module to the list and make sure it's required */ 01117 add_to_load_order(v->value, &load_order, 1); 01118 ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name); 01119 } 01120 01121 } 01122 01123 /* check if 'autoload' is on */ 01124 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 01125 /* if so, first add all the embedded modules that are not already running to the load order */ 01126 AST_LIST_TRAVERSE(&module_list, mod, entry) { 01127 /* if it's not embedded, skip it */ 01128 if (mod->lib) 01129 continue; 01130 01131 if (mod->flags.running) 01132 continue; 01133 01134 add_to_load_order(mod->resource, &load_order, 0); 01135 } 01136 01137 #ifdef LOADABLE_MODULES 01138 /* if we are allowed to load dynamic modules, scan the directory for 01139 for all available modules and add them as well */ 01140 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 01141 while ((dirent = readdir(dir))) { 01142 int ld = strlen(dirent->d_name); 01143 01144 /* Must end in .so to load it. */ 01145 01146 if (ld < 4) 01147 continue; 01148 01149 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 01150 continue; 01151 01152 /* if there is already a module by this name in the module_list, 01153 skip this file */ 01154 if (find_resource(dirent->d_name, 0)) 01155 continue; 01156 01157 add_to_load_order(dirent->d_name, &load_order, 0); 01158 } 01159 01160 closedir(dir); 01161 } else { 01162 if (!ast_opt_quiet) 01163 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 01164 ast_config_AST_MODULE_DIR); 01165 } 01166 #endif 01167 } 01168 01169 /* now scan the config for any modules we are prohibited from loading and 01170 remove them from the load order */ 01171 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 01172 if (strcasecmp(v->name, "noload")) 01173 continue; 01174 01175 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 01176 if (!resource_name_match(order->resource, v->value)) { 01177 AST_LIST_REMOVE_CURRENT(entry); 01178 ast_free(order->resource); 01179 ast_free(order); 01180 } 01181 } 01182 AST_LIST_TRAVERSE_SAFE_END; 01183 } 01184 01185 /* we are done with the config now, all the information we need is in the 01186 load_order list */ 01187 ast_config_destroy(cfg); 01188 01189 load_count = 0; 01190 AST_LIST_TRAVERSE(&load_order, order, entry) 01191 load_count++; 01192 01193 if (load_count) 01194 ast_log(LOG_NOTICE, "%u modules will be loaded.\n", load_count); 01195 01196 /* first, load only modules that provide global symbols */ 01197 if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) { 01198 goto done; 01199 } 01200 01201 /* now load everything else */ 01202 if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) { 01203 goto done; 01204 } 01205 01206 done: 01207 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 01208 ast_free(order->resource); 01209 ast_free(order); 01210 } 01211 01212 AST_LIST_UNLOCK(&module_list); 01213 01214 /* Tell manager clients that are aggressive at logging in that we're done 01215 loading modules. If there's a DNS problem in chan_sip, we might not 01216 even reach this */ 01217 manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount); 01218 01219 return res; 01220 }
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 893 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().
00894 { 00895 struct ast_module *mod; 00896 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00897 00898 if ((mod = find_resource(resource_name, 0))) { 00899 if (mod->flags.running) { 00900 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00901 return AST_MODULE_LOAD_DECLINE; 00902 } 00903 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00904 return AST_MODULE_LOAD_SKIP; 00905 } else { 00906 #ifdef LOADABLE_MODULES 00907 if (!(mod = load_dynamic_module(resource_name, global_symbols_only, resource_heap))) { 00908 /* don't generate a warning message during load_modules() */ 00909 if (!global_symbols_only) { 00910 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00911 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; 00912 } else { 00913 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP; 00914 } 00915 } 00916 #else 00917 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00918 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; 00919 #endif 00920 } 00921 00922 if (inspect_module(mod)) { 00923 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00924 #ifdef LOADABLE_MODULES 00925 unload_dynamic_module(mod); 00926 #endif 00927 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; 00928 } 00929 00930 if (!mod->lib && mod->info->backup_globals && mod->info->backup_globals()) { 00931 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name); 00932 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; 00933 } 00934 00935 mod->flags.declined = 0; 00936 00937 if (resource_heap) { 00938 ast_heap_push(resource_heap, mod); 00939 res = AST_MODULE_LOAD_PRIORITY; 00940 } else { 00941 res = start_resource(mod); 00942 } 00943 00944 return res; 00945 }
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 1010 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().
01011 { 01012 struct ast_heap *resource_heap; 01013 struct load_order_entry *order; 01014 struct ast_module *mod; 01015 int count = 0; 01016 int res = 0; 01017 01018 if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) { 01019 return -1; 01020 } 01021 01022 /* first, add find and add modules to heap */ 01023 AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) { 01024 switch (load_resource(order->resource, global_symbols, resource_heap, order->required)) { 01025 case AST_MODULE_LOAD_SUCCESS: 01026 case AST_MODULE_LOAD_DECLINE: 01027 AST_LIST_REMOVE_CURRENT(entry); 01028 ast_free(order->resource); 01029 ast_free(order); 01030 break; 01031 case AST_MODULE_LOAD_FAILURE: 01032 ast_log(LOG_ERROR, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required"); 01033 fprintf(stderr, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required"); 01034 res = order->required ? -2 : -1; 01035 goto done; 01036 case AST_MODULE_LOAD_SKIP: 01037 break; 01038 case AST_MODULE_LOAD_PRIORITY: 01039 AST_LIST_REMOVE_CURRENT(entry); 01040 ast_free(order->resource); 01041 ast_free(order); 01042 break; 01043 } 01044 } 01045 AST_LIST_TRAVERSE_SAFE_END; 01046 01047 /* second remove modules from heap sorted by priority */ 01048 while ((mod = ast_heap_pop(resource_heap))) { 01049 switch (start_resource(mod)) { 01050 case AST_MODULE_LOAD_SUCCESS: 01051 count++; 01052 case AST_MODULE_LOAD_DECLINE: 01053 break; 01054 case AST_MODULE_LOAD_FAILURE: 01055 res = -1; 01056 goto done; 01057 case AST_MODULE_LOAD_SKIP: 01058 case AST_MODULE_LOAD_PRIORITY: 01059 break; 01060 } 01061 } 01062 01063 done: 01064 if (mod_count) { 01065 *mod_count += count; 01066 } 01067 ast_heap_destroy(resource_heap); 01068 01069 return res; 01070 }
static int mod_load_cmp | ( | void * | a, | |
void * | b | |||
) | [static] |
Definition at line 991 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().
00992 { 00993 struct ast_module *a_mod = (struct ast_module *) a; 00994 struct ast_module *b_mod = (struct ast_module *) b; 00995 int res = -1; 00996 /* if load_pri is not set, default is 128. Lower is better*/ 00997 unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128; 00998 unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128; 00999 if (a_pri == b_pri) { 01000 res = 0; 01001 } else if (a_pri < b_pri) { 01002 res = 1; 01003 } 01004 return res; 01005 }
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", (unsigned)*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 683 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().
00684 { 00685 struct reload_queue_item *item; 00686 00687 AST_LIST_LOCK(&reload_queue); 00688 00689 if (do_full_reload) { 00690 AST_LIST_UNLOCK(&reload_queue); 00691 return; 00692 } 00693 00694 if (ast_strlen_zero(module)) { 00695 /* A full reload request (when module is NULL) wipes out any previous 00696 reload requests and causes the queue to ignore future ones */ 00697 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) { 00698 ast_free(item); 00699 } 00700 do_full_reload = 1; 00701 } else { 00702 /* No reason to add the same module twice */ 00703 AST_LIST_TRAVERSE(&reload_queue, item, entry) { 00704 if (!strcasecmp(item->module, module)) { 00705 AST_LIST_UNLOCK(&reload_queue); 00706 return; 00707 } 00708 } 00709 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1); 00710 if (!item) { 00711 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n"); 00712 AST_LIST_UNLOCK(&reload_queue); 00713 return; 00714 } 00715 strcpy(item->module, module); 00716 AST_LIST_INSERT_TAIL(&reload_queue, item, entry); 00717 } 00718 AST_LIST_UNLOCK(&reload_queue); 00719 }
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 843 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().
00844 { 00845 char tmp[256]; 00846 enum ast_module_load_result res; 00847 00848 if (mod->flags.running) { 00849 return AST_MODULE_LOAD_SUCCESS; 00850 } 00851 00852 if (!mod->info->load) { 00853 return AST_MODULE_LOAD_FAILURE; 00854 } 00855 00856 res = mod->info->load(); 00857 00858 switch (res) { 00859 case AST_MODULE_LOAD_SUCCESS: 00860 if (!ast_fully_booted) { 00861 ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00862 if (ast_opt_console && !option_verbose) 00863 ast_verbose( "."); 00864 } else { 00865 ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description); 00866 } 00867 00868 mod->flags.running = 1; 00869 00870 ast_update_use_count(); 00871 break; 00872 case AST_MODULE_LOAD_DECLINE: 00873 mod->flags.declined = 1; 00874 break; 00875 case AST_MODULE_LOAD_FAILURE: 00876 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */ 00877 case AST_MODULE_LOAD_PRIORITY: 00878 break; 00879 } 00880 00881 return res; 00882 }
static void unload_dynamic_module | ( | struct ast_module * | mod | ) | [static] |
Definition at line 393 of file loader.c.
References ast_module_name(), close_lib(), and ast_module::lib.
Referenced by ast_unload_resource(), and load_resource().
00394 { 00395 void *lib = mod->lib; 00396 00397 /* WARNING: the structure pointed to by mod is going to 00398 disappear when this operation succeeds, so we can't 00399 dereference it */ 00400 close_lib(ast_module_name(mod), lib); 00401 }
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().