#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 <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 | |
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 with the name given is loaded. | |
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. | |
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) |
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 |
Kevin P. Fleming <kpfleming@digium.com>
Luigi Rizzo <rizzo@icir.org>
Definition in file loader.c.
#define RTLD_LOCAL 0 |
#define RTLD_NOW 0 |
struct ast_module_user* __ast_module_user_add | ( | struct ast_module * | mod, | |
struct ast_channel * | chan | |||
) |
Definition at line 208 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_user::entry, 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 = ast_calloc(1, sizeof(*u)); 00212 00213 if (!u) 00214 return NULL; 00215 00216 u->chan = chan; 00217 00218 AST_LIST_LOCK(&mod->users); 00219 AST_LIST_INSERT_HEAD(&mod->users, u, entry); 00220 AST_LIST_UNLOCK(&mod->users); 00221 00222 ast_atomic_fetchadd_int(&mod->usecount, +1); 00223 00224 ast_update_use_count(); 00225 00226 return u; 00227 }
void __ast_module_user_hangup_all | ( | struct ast_module * | mod | ) |
Definition at line 240 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_user::entry, ast_module::usecount, and ast_module::users.
Referenced by ast_unload_resource().
00241 { 00242 struct ast_module_user *u; 00243 00244 AST_LIST_LOCK(&mod->users); 00245 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) { 00246 if (u->chan) { 00247 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD); 00248 } 00249 ast_atomic_fetchadd_int(&mod->usecount, -1); 00250 ast_free(u); 00251 } 00252 AST_LIST_UNLOCK(&mod->users); 00253 00254 ast_update_use_count(); 00255 }
void __ast_module_user_remove | ( | struct ast_module * | mod, | |
struct ast_module_user * | u | |||
) |
Definition at line 229 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_user::entry, ast_module::usecount, and ast_module::users.
Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and pbx_exec().
00230 { 00231 AST_LIST_LOCK(&mod->users); 00232 AST_LIST_REMOVE(&mod->users, u, entry); 00233 AST_LIST_UNLOCK(&mod->users); 00234 ast_atomic_fetchadd_int(&mod->usecount, -1); 00235 ast_free(u); 00236 00237 ast_update_use_count(); 00238 }
static struct load_order_entry* add_to_load_order | ( | const char * | resource, | |
struct load_order * | load_order, | |||
int | required | |||
) | [static] |
Definition at line 909 of file loader.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, ast_module_user::entry, load_order_entry::required, load_order_entry::resource, and resource_name_match().
Referenced by load_modules().
00910 { 00911 struct load_order_entry *order; 00912 00913 AST_LIST_TRAVERSE(load_order, order, entry) { 00914 if (!resource_name_match(order->resource, resource)) { 00915 /* Make sure we have the proper setting for the required field 00916 (we might have both load= and required= lines in modules.conf) */ 00917 order->required |= required; 00918 return NULL; 00919 } 00920 } 00921 00922 if (!(order = ast_calloc(1, sizeof(*order)))) 00923 return NULL; 00924 00925 order->resource = ast_strdup(resource); 00926 order->required = required; 00927 AST_LIST_INSERT_TAIL(load_order, order, entry); 00928 00929 return order; 00930 }
int ast_load_resource | ( | const char * | resource_name | ) |
Load a module.
resource_name | The name of the module to load. |
Definition at line 891 of file loader.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, and load_resource().
Referenced by handle_load(), load_module(), and manager_moduleload().
00892 { 00893 int res; 00894 AST_LIST_LOCK(&module_list); 00895 res = load_resource(resource_name, 0, NULL, 0); 00896 AST_LIST_UNLOCK(&module_list); 00897 00898 return res; 00899 }
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. |
0 | on success | |
-1 | on failure. |
Definition at line 1207 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_malloc, and ast_module_user::entry.
01208 { 01209 struct loadupdate *tmp; 01210 01211 if (!(tmp = ast_malloc(sizeof(*tmp)))) 01212 return -1; 01213 01214 tmp->updater = v; 01215 AST_LIST_LOCK(&updaters); 01216 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 01217 AST_LIST_UNLOCK(&updaters); 01218 01219 return 0; 01220 }
int ast_loader_unregister | ( | int(*)(void) | updater | ) |
Remove a procedure to be run when modules are updated.
updater | The updater function to unregister. |
0 | on success | |
-1 | on failure. |
Definition at line 1222 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, ast_module_user::entry, and loadupdate::updater.
01223 { 01224 struct loadupdate *cur; 01225 01226 AST_LIST_LOCK(&updaters); 01227 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 01228 if (cur->updater == v) { 01229 AST_LIST_REMOVE_CURRENT(entry); 01230 break; 01231 } 01232 } 01233 AST_LIST_TRAVERSE_SAFE_END; 01234 AST_LIST_UNLOCK(&updaters); 01235 01236 return cur ? 0 : -1; 01237 }
int ast_module_check | ( | const char * | name | ) |
Check if module with the name given is loaded.
name | Module name, like "chan_sip.so" |
1 | if true | |
0 | if false |
Definition at line 1194 of file loader.c.
References ast_strlen_zero(), and find_resource().
Referenced by ifmodule_read(), load_module(), manager_modulecheck(), and unload_module().
01195 { 01196 struct ast_module *cur; 01197 01198 if (ast_strlen_zero(name)) 01199 return 0; /* FALSE */ 01200 01201 cur = find_resource(name, 1); 01202 01203 return (cur != NULL); 01204 }
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 580 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_module_user::entry, 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().
00581 { 00582 struct ast_module *cur; 00583 int i, which=0, l = strlen(word); 00584 char *ret = NULL; 00585 00586 if (pos != rpos) 00587 return NULL; 00588 00589 AST_LIST_LOCK(&module_list); 00590 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00591 if (!strncasecmp(word, cur->resource, l) && 00592 (cur->info->reload || !needsreload) && 00593 ++which > state) { 00594 ret = ast_strdup(cur->resource); 00595 break; 00596 } 00597 } 00598 AST_LIST_UNLOCK(&module_list); 00599 00600 if (!ret) { 00601 for (i=0; !ret && reload_classes[i].name; i++) { 00602 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00603 ret = ast_strdup(reload_classes[i].name); 00604 } 00605 } 00606 00607 return ret; 00608 }
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 103 of file loader.c.
Referenced by acf_retrieve_docs(), and ast_register_application2().
00104 { 00105 if (!mod || !mod->info) { 00106 return NULL; 00107 } 00108 00109 return mod->info->name; 00110 }
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) |
Definition at line 1239 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(), dahdi_pri_cc_agent_init(), 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(), mgcp_new(), moh_alloc(), moh_files_alloc(), mute_add_audiohook(), my_module_ref(), newpvt(), oss_new(), phone_check_exception(), phone_new(), sip_handle_cc(), sip_new(), and skinny_new().
01240 { 01241 if (!mod) { 01242 return NULL; 01243 } 01244 01245 ast_atomic_fetchadd_int(&mod->usecount, +1); 01246 ast_update_use_count(); 01247 01248 return mod; 01249 }
void ast_module_register | ( | const struct ast_module_info * | info | ) |
Definition at line 146 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_user::entry, ast_module::info, and ast_module::users.
00147 { 00148 struct ast_module *mod; 00149 00150 if (embedding) { 00151 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1))) 00152 return; 00153 strcpy(mod->resource, info->name); 00154 } else { 00155 mod = resource_being_loaded; 00156 } 00157 00158 mod->info = info; 00159 AST_LIST_HEAD_INIT(&mod->users); 00160 00161 /* during startup, before the loader has been initialized, 00162 there are no threads, so there is no need to take the lock 00163 on this list to manipulate it. it is also possible that it 00164 might be unsafe to use the list lock at that point... so 00165 let's avoid it altogether 00166 */ 00167 if (embedding) { 00168 AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry); 00169 } else { 00170 AST_LIST_LOCK(&module_list); 00171 /* it is paramount that the new entry be placed at the tail of 00172 the list, otherwise the code that uses dlopen() to load 00173 dynamic modules won't be able to find out if the module it 00174 just opened was registered or failed to load 00175 */ 00176 AST_LIST_INSERT_TAIL(&module_list, mod, entry); 00177 AST_LIST_UNLOCK(&module_list); 00178 } 00179 00180 /* give the module a copy of its own handle, for later use in registrations and the like */ 00181 *((struct ast_module **) &(info->self)) = mod; 00182 }
int ast_module_reload | ( | const char * | name | ) |
Reload asterisk modules.
name | the name of the module to reload |
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 675 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_tvnow(), ast_unlock_path(), ast_verb, ast_verbose, ast_module::declined, ast_module_info::description, ast_module_user::entry, 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().
00676 { 00677 struct ast_module *cur; 00678 int res = 0; /* return value. 0 = not found, others, see below */ 00679 int i; 00680 00681 /* If we aren't fully booted, we just pretend we reloaded but we queue this 00682 up to run once we are booted up. */ 00683 if (!ast_fully_booted) { 00684 queue_reload_request(name); 00685 return 0; 00686 } 00687 00688 if (ast_mutex_trylock(&reloadlock)) { 00689 ast_verbose("The previous reload command didn't finish yet\n"); 00690 return -1; /* reload already in progress */ 00691 } 00692 ast_lastreloadtime = ast_tvnow(); 00693 00694 if (ast_opt_lock_confdir) { 00695 int try; 00696 int res; 00697 for (try = 1, res = AST_LOCK_TIMEOUT; try < 6 && (res == AST_LOCK_TIMEOUT); try++) { 00698 res = ast_lock_path(ast_config_AST_CONFIG_DIR); 00699 if (res == AST_LOCK_TIMEOUT) { 00700 ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try); 00701 } 00702 } 00703 if (res != AST_LOCK_SUCCESS) { 00704 ast_verbose("Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR); 00705 ast_mutex_unlock(&reloadlock); 00706 return -1; 00707 } 00708 } 00709 00710 /* Call "predefined" reload here first */ 00711 for (i = 0; reload_classes[i].name; i++) { 00712 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00713 reload_classes[i].reload_fn(); /* XXX should check error ? */ 00714 res = 2; /* found and reloaded */ 00715 } 00716 } 00717 00718 if (name && res) { 00719 if (ast_opt_lock_confdir) { 00720 ast_unlock_path(ast_config_AST_CONFIG_DIR); 00721 } 00722 ast_mutex_unlock(&reloadlock); 00723 return res; 00724 } 00725 00726 AST_LIST_LOCK(&module_list); 00727 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00728 const struct ast_module_info *info = cur->info; 00729 00730 if (name && resource_name_match(name, cur->resource)) 00731 continue; 00732 00733 if (!cur->flags.running || cur->flags.declined) { 00734 if (!name) 00735 continue; 00736 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. " 00737 "Before reloading the module, you must run \"module load %s\" " 00738 "and fix whatever is preventing the module from being initialized.\n", 00739 name, name); 00740 res = 2; /* Don't report that the module was not found */ 00741 break; 00742 } 00743 00744 if (!info->reload) { /* cannot be reloaded */ 00745 if (res < 1) /* store result if possible */ 00746 res = 1; /* 1 = no reload() method */ 00747 continue; 00748 } 00749 00750 res = 2; 00751 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description); 00752 info->reload(); 00753 } 00754 AST_LIST_UNLOCK(&module_list); 00755 00756 if (ast_opt_lock_confdir) { 00757 ast_unlock_path(ast_config_AST_CONFIG_DIR); 00758 } 00759 ast_mutex_unlock(&reloadlock); 00760 00761 return res; 00762 }
void ast_module_shutdown | ( | void | ) |
Run the unload() callback for all loaded modules.
This function should be called when Asterisk is shutting down gracefully.
If we go through the entire list without changing anything, ignore the usecounts and unload, then exit.
Definition at line 480 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_user::entry, 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().
00481 { 00482 struct ast_module *mod; 00483 int somethingchanged = 1, final = 0; 00484 00485 AST_LIST_LOCK(&module_list); 00486 00487 /*!\note Some resources, like timers, are started up dynamically, and thus 00488 * may be still in use, even if all channels are dead. We must therefore 00489 * check the usecount before asking modules to unload. */ 00490 do { 00491 if (!somethingchanged) { 00492 /*!\note If we go through the entire list without changing 00493 * anything, ignore the usecounts and unload, then exit. */ 00494 final = 1; 00495 } 00496 00497 /* Reset flag before traversing the list */ 00498 somethingchanged = 0; 00499 00500 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) { 00501 if (!final && mod->usecount) { 00502 continue; 00503 } 00504 AST_LIST_REMOVE_CURRENT(entry); 00505 if (mod->flags.running && !mod->flags.declined && mod->info->unload) { 00506 mod->info->unload(); 00507 } 00508 AST_LIST_HEAD_DESTROY(&mod->users); 00509 free(mod); 00510 somethingchanged = 1; 00511 } 00512 AST_LIST_TRAVERSE_SAFE_END; 00513 } while (somethingchanged && !final); 00514 00515 AST_LIST_UNLOCK(&module_list); 00516 }
void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 1251 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(), dahdi_pri_cc_agent_destructor(), dahdi_pri_cc_agent_init(), 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(), mgcp_hangup(), my_module_unref(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_cc_monitor_destructor(), sip_hangup(), skinny_hangup(), and smart_bridge_operation().
01252 { 01253 if (!mod) { 01254 return; 01255 } 01256 01257 ast_atomic_fetchadd_int(&mod->usecount, -1); 01258 ast_update_use_count(); 01259 }
void ast_module_unregister | ( | const struct ast_module_info * | info | ) |
Definition at line 184 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_user::entry, ast_module::info, and ast_module::users.
00185 { 00186 struct ast_module *mod = NULL; 00187 00188 /* it is assumed that the users list in the module structure 00189 will already be empty, or we cannot have gotten to this 00190 point 00191 */ 00192 AST_LIST_LOCK(&module_list); 00193 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) { 00194 if (mod->info == info) { 00195 AST_LIST_REMOVE_CURRENT(entry); 00196 break; 00197 } 00198 } 00199 AST_LIST_TRAVERSE_SAFE_END; 00200 AST_LIST_UNLOCK(&module_list); 00201 00202 if (mod) { 00203 AST_LIST_HEAD_DESTROY(&mod->users); 00204 ast_free(mod); 00205 } 00206 }
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 610 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, ast_module_user::entry, LOG_NOTICE, and reload_queue_item::module.
Referenced by main().
00611 { 00612 struct reload_queue_item *item; 00613 00614 if (!ast_fully_booted) { 00615 return; 00616 } 00617 00618 AST_LIST_LOCK(&reload_queue); 00619 00620 if (do_full_reload) { 00621 do_full_reload = 0; 00622 AST_LIST_UNLOCK(&reload_queue); 00623 ast_log(LOG_NOTICE, "Executing deferred reload request.\n"); 00624 ast_module_reload(NULL); 00625 return; 00626 } 00627 00628 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) { 00629 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module); 00630 ast_module_reload(item->module); 00631 ast_free(item); 00632 } 00633 00634 AST_LIST_UNLOCK(&reload_queue); 00635 }
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. |
0 | on success. | |
-1 | on error. |
Definition at line 518 of file loader.c.
References __ast_module_user_hangup_all(), AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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, unload_dynamic_module(), and ast_module::usecount.
Referenced by handle_unload(), manager_moduleload(), and unload_module().
00519 { 00520 struct ast_module *mod; 00521 int res = -1; 00522 int error = 0; 00523 00524 AST_LIST_LOCK(&module_list); 00525 00526 if (!(mod = find_resource(resource_name, 0))) { 00527 AST_LIST_UNLOCK(&module_list); 00528 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name); 00529 return -1; 00530 } 00531 00532 if (!mod->flags.running || mod->flags.declined) { 00533 ast_log(LOG_WARNING, "Unload failed, '%s' is not loaded.\n", resource_name); 00534 error = 1; 00535 } 00536 00537 if (!error && (mod->usecount > 0)) { 00538 if (force) 00539 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00540 resource_name, mod->usecount); 00541 else { 00542 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00543 mod->usecount); 00544 error = 1; 00545 } 00546 } 00547 00548 if (!error) { 00549 __ast_module_user_hangup_all(mod); 00550 res = mod->info->unload(); 00551 00552 if (res) { 00553 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00554 if (force <= AST_FORCE_FIRM) 00555 error = 1; 00556 else 00557 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00558 } 00559 } 00560 00561 if (!error) 00562 mod->flags.running = mod->flags.declined = 0; 00563 00564 AST_LIST_UNLOCK(&module_list); 00565 00566 if (!error && !mod->lib && mod->info && mod->info->restore_globals) 00567 mod->info->restore_globals(); 00568 00569 #ifdef LOADABLE_MODULES 00570 if (!error) 00571 unload_dynamic_module(mod); 00572 #endif 00573 00574 if (!error) 00575 ast_update_use_count(); 00576 00577 return res; 00578 }
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 1173 of file loader.c.
References AST_LIST_TRAVERSE, AST_LIST_TRYLOCK, AST_LIST_UNLOCK, ast_module_info::description, ast_module_user::entry, ast_module::info, ast_module::resource, and ast_module::usecount.
Referenced by ast_var_Modules(), and handle_modlist().
01175 { 01176 struct ast_module *cur; 01177 int unlock = -1; 01178 int total_mod_loaded = 0; 01179 01180 if (AST_LIST_TRYLOCK(&module_list)) 01181 unlock = 0; 01182 01183 AST_LIST_TRAVERSE(&module_list, cur, entry) { 01184 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 01185 } 01186 01187 if (unlock) 01188 AST_LIST_UNLOCK(&module_list); 01189 01190 return total_mod_loaded; 01191 }
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 1161 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_module_user::entry, 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().
01162 { 01163 /* Notify any module monitors that the use count for a 01164 resource has changed */ 01165 struct loadupdate *m; 01166 01167 AST_LIST_LOCK(&updaters); 01168 AST_LIST_TRAVERSE(&updaters, m, entry) 01169 m->updater(); 01170 AST_LIST_UNLOCK(&updaters); 01171 }
static struct ast_module* find_resource | ( | const char * | resource, | |
int | do_lock | |||
) | [static] |
Definition at line 342 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_module_user::entry, ast_module::resource, and resource_name_match().
Referenced by ast_module_check(), ast_unload_resource(), load_dynamic_module(), and load_resource().
00343 { 00344 struct ast_module *cur; 00345 00346 if (do_lock) 00347 AST_LIST_LOCK(&module_list); 00348 00349 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00350 if (!resource_name_match(resource, cur->resource)) 00351 break; 00352 } 00353 00354 if (do_lock) 00355 AST_LIST_UNLOCK(&module_list); 00356 00357 return cur; 00358 }
static unsigned int inspect_module | ( | const struct ast_module * | mod | ) | [static] |
Definition at line 764 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().
00765 { 00766 if (!mod->info->description) { 00767 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00768 return 1; 00769 } 00770 00771 if (!mod->info->key) { 00772 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00773 return 1; 00774 } 00775 00776 if (verify_key((unsigned char *) mod->info->key)) { 00777 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00778 return 1; 00779 } 00780 00781 if (!ast_strlen_zero(mod->info->buildopt_sum) && 00782 strcmp(buildopt_sum, mod->info->buildopt_sum)) { 00783 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource); 00784 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource); 00785 return 1; 00786 } 00787 00788 return 0; 00789 }
static int key_matches | ( | const unsigned char * | key1, | |
const unsigned char * | key2 | |||
) | [static] |
Definition at line 295 of file loader.c.
Referenced by verify_key().
00296 { 00297 int x; 00298 00299 for (x = 0; x < 16; x++) { 00300 if (key1[x] != key2[x]) 00301 return 0; 00302 } 00303 00304 return 1; 00305 }
static struct ast_module* load_dynamic_module | ( | const char * | resource_in, | |
unsigned int | global_symbols_only | |||
) | [static] |
Definition at line 373 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, LOG_WARNING, ast_module_info::nonoptreq, ast_module::resource, resource_being_loaded, RTLD_LOCAL, RTLD_NOW, and strsep().
Referenced by load_resource().
00374 { 00375 char fn[PATH_MAX] = ""; 00376 void *lib = NULL; 00377 struct ast_module *mod; 00378 unsigned int wants_global; 00379 int space; /* room needed for the descriptor */ 00380 int missing_so = 0; 00381 00382 space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1; 00383 if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) { 00384 missing_so = 1; 00385 space += 3; /* room for the extra ".so" */ 00386 } 00387 00388 snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : ""); 00389 00390 /* make a first load of the module in 'quiet' mode... don't try to resolve 00391 any symbols, and don't export any symbols. this will allow us to peek into 00392 the module's info block (if available) to see what flags it has set */ 00393 00394 resource_being_loaded = ast_calloc(1, space); 00395 if (!resource_being_loaded) 00396 return NULL; 00397 strcpy(resource_being_loaded->resource, resource_in); 00398 if (missing_so) 00399 strcat(resource_being_loaded->resource, ".so"); 00400 00401 if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) { 00402 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); 00403 ast_free(resource_being_loaded); 00404 return NULL; 00405 } 00406 00407 /* the dlopen() succeeded, let's find out if the module 00408 registered itself */ 00409 /* note that this will only work properly as long as 00410 ast_module_register() (which is called by the module's 00411 constructor) places the new module at the tail of the 00412 module_list 00413 */ 00414 if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) { 00415 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in); 00416 /* no, it did not, so close it and return */ 00417 while (!dlclose(lib)); 00418 /* note that the module's destructor will call ast_module_unregister(), 00419 which will free the structure we allocated in resource_being_loaded */ 00420 return NULL; 00421 } 00422 00423 wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS); 00424 00425 /* if we are being asked only to load modules that provide global symbols, 00426 and this one does not, then close it and return */ 00427 if (global_symbols_only && !wants_global) { 00428 while (!dlclose(lib)); 00429 return NULL; 00430 } 00431 00432 /* This section is a workaround for a gcc 4.1 bug that has already been 00433 * fixed in later versions. Unfortunately, some distributions, such as 00434 * RHEL/CentOS 5, distribute gcc 4.1, so we're stuck with having to deal 00435 * with this issue. This basically ensures that optional_api modules are 00436 * loaded before any module which requires their functionality. */ 00437 #if !defined(HAVE_ATTRIBUTE_weak_import) && !defined(HAVE_ATTRIBUTE_weakref) 00438 if (!ast_strlen_zero(mod->info->nonoptreq)) { 00439 /* Force any required dependencies to load */ 00440 char *each, *required_resource = ast_strdupa(mod->info->nonoptreq); 00441 while ((each = strsep(&required_resource, ","))) { 00442 each = ast_strip(each); 00443 00444 /* Is it already loaded? */ 00445 if (!find_resource(each, 0)) { 00446 load_dynamic_module(each, global_symbols_only); 00447 } 00448 } 00449 } 00450 #endif 00451 00452 while (!dlclose(lib)); 00453 resource_being_loaded = NULL; 00454 00455 /* start the load process again */ 00456 resource_being_loaded = ast_calloc(1, space); 00457 if (!resource_being_loaded) 00458 return NULL; 00459 strcpy(resource_being_loaded->resource, resource_in); 00460 if (missing_so) 00461 strcat(resource_being_loaded->resource, ".so"); 00462 00463 if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) { 00464 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); 00465 ast_free(resource_being_loaded); 00466 return NULL; 00467 } 00468 00469 /* since the module was successfully opened, and it registered itself 00470 the previous time we did that, we're going to assume it worked this 00471 time too :) */ 00472 00473 AST_LIST_LAST(&module_list)->lib = lib; 00474 resource_being_loaded = NULL; 00475 00476 return AST_LIST_LAST(&module_list); 00477 }
int load_modules | ( | unsigned | int | ) |
Provided by loader.c
Definition at line 1011 of file loader.c.
References add_to_load_order(), ast_config_load2(), ast_debug, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, ast_log(), AST_MODULE_CONFIG, ast_variable_browse(), ast_verb, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, embedded_module_list, embedding, module_list::first, module_list::last, LOG_WARNING, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by main().
01012 { 01013 struct ast_config *cfg; 01014 struct ast_module *mod; 01015 struct load_order_entry *order; 01016 struct ast_variable *v; 01017 unsigned int load_count; 01018 struct load_order load_order; 01019 int res = 0; 01020 struct ast_flags config_flags = { 0 }; 01021 int modulecount = 0; 01022 01023 #ifdef LOADABLE_MODULES 01024 struct dirent *dirent; 01025 DIR *dir; 01026 #endif 01027 01028 /* all embedded modules have registered themselves by now */ 01029 embedding = 0; 01030 01031 ast_verb(1, "Asterisk Dynamic Loader Starting:\n"); 01032 01033 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 01034 01035 AST_LIST_LOCK(&module_list); 01036 01037 if (embedded_module_list.first) { 01038 module_list.first = embedded_module_list.first; 01039 module_list.last = embedded_module_list.last; 01040 embedded_module_list.first = NULL; 01041 } 01042 01043 cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags); 01044 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 01045 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 01046 goto done; 01047 } 01048 01049 /* first, find all the modules we have been explicitly requested to load */ 01050 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 01051 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) { 01052 add_to_load_order(v->value, &load_order, 0); 01053 } 01054 if (!strcasecmp(v->name, preload_only ? "preload-require" : "require")) { 01055 /* Add the module to the list and make sure it's required */ 01056 add_to_load_order(v->value, &load_order, 1); 01057 ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name); 01058 } 01059 01060 } 01061 01062 /* check if 'autoload' is on */ 01063 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 01064 /* if so, first add all the embedded modules that are not already running to the load order */ 01065 AST_LIST_TRAVERSE(&module_list, mod, entry) { 01066 /* if it's not embedded, skip it */ 01067 if (mod->lib) 01068 continue; 01069 01070 if (mod->flags.running) 01071 continue; 01072 01073 add_to_load_order(mod->resource, &load_order, 0); 01074 } 01075 01076 #ifdef LOADABLE_MODULES 01077 /* if we are allowed to load dynamic modules, scan the directory for 01078 for all available modules and add them as well */ 01079 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 01080 while ((dirent = readdir(dir))) { 01081 int ld = strlen(dirent->d_name); 01082 01083 /* Must end in .so to load it. */ 01084 01085 if (ld < 4) 01086 continue; 01087 01088 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 01089 continue; 01090 01091 /* if there is already a module by this name in the module_list, 01092 skip this file */ 01093 if (find_resource(dirent->d_name, 0)) 01094 continue; 01095 01096 add_to_load_order(dirent->d_name, &load_order, 0); 01097 } 01098 01099 closedir(dir); 01100 } else { 01101 if (!ast_opt_quiet) 01102 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 01103 ast_config_AST_MODULE_DIR); 01104 } 01105 #endif 01106 } 01107 01108 /* now scan the config for any modules we are prohibited from loading and 01109 remove them from the load order */ 01110 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 01111 if (strcasecmp(v->name, "noload")) 01112 continue; 01113 01114 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 01115 if (!resource_name_match(order->resource, v->value)) { 01116 AST_LIST_REMOVE_CURRENT(entry); 01117 ast_free(order->resource); 01118 ast_free(order); 01119 } 01120 } 01121 AST_LIST_TRAVERSE_SAFE_END; 01122 } 01123 01124 /* we are done with the config now, all the information we need is in the 01125 load_order list */ 01126 ast_config_destroy(cfg); 01127 01128 load_count = 0; 01129 AST_LIST_TRAVERSE(&load_order, order, entry) 01130 load_count++; 01131 01132 if (load_count) 01133 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count); 01134 01135 /* first, load only modules that provide global symbols */ 01136 if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) { 01137 goto done; 01138 } 01139 01140 /* now load everything else */ 01141 if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) { 01142 goto done; 01143 } 01144 01145 done: 01146 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 01147 ast_free(order->resource); 01148 ast_free(order); 01149 } 01150 01151 AST_LIST_UNLOCK(&module_list); 01152 01153 /* Tell manager clients that are aggressive at logging in that we're done 01154 loading modules. If there's a DNS problem in chan_sip, we might not 01155 even reach this */ 01156 manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount); 01157 01158 return res; 01159 }
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 837 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(), and load_resource_list().
00838 { 00839 struct ast_module *mod; 00840 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00841 00842 if ((mod = find_resource(resource_name, 0))) { 00843 if (mod->flags.running) { 00844 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00845 return AST_MODULE_LOAD_DECLINE; 00846 } 00847 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00848 return AST_MODULE_LOAD_SKIP; 00849 } else { 00850 #ifdef LOADABLE_MODULES 00851 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) { 00852 /* don't generate a warning message during load_modules() */ 00853 if (!global_symbols_only) { 00854 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00855 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; 00856 } else { 00857 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP; 00858 } 00859 } 00860 #else 00861 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00862 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; 00863 #endif 00864 } 00865 00866 if (inspect_module(mod)) { 00867 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00868 #ifdef LOADABLE_MODULES 00869 unload_dynamic_module(mod); 00870 #endif 00871 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; 00872 } 00873 00874 if (!mod->lib && mod->info->backup_globals && mod->info->backup_globals()) { 00875 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name); 00876 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; 00877 } 00878 00879 mod->flags.declined = 0; 00880 00881 if (resource_heap) { 00882 ast_heap_push(resource_heap, mod); 00883 res = AST_MODULE_LOAD_PRIORITY; 00884 } else { 00885 res = start_resource(mod); 00886 } 00887 00888 return res; 00889 }
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 951 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, ast_module_user::entry, load_resource(), LOG_ERROR, mod_load_cmp(), load_order_entry::required, load_order_entry::resource, and start_resource().
00952 { 00953 struct ast_heap *resource_heap; 00954 struct load_order_entry *order; 00955 struct ast_module *mod; 00956 int count = 0; 00957 int res = 0; 00958 00959 if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) { 00960 return -1; 00961 } 00962 00963 /* first, add find and add modules to heap */ 00964 AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) { 00965 switch (load_resource(order->resource, global_symbols, resource_heap, order->required)) { 00966 case AST_MODULE_LOAD_SUCCESS: 00967 case AST_MODULE_LOAD_DECLINE: 00968 AST_LIST_REMOVE_CURRENT(entry); 00969 ast_free(order->resource); 00970 ast_free(order); 00971 break; 00972 case AST_MODULE_LOAD_FAILURE: 00973 ast_log(LOG_ERROR, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required"); 00974 fprintf(stderr, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required"); 00975 res = order->required ? -2 : -1; 00976 goto done; 00977 case AST_MODULE_LOAD_SKIP: 00978 break; 00979 case AST_MODULE_LOAD_PRIORITY: 00980 AST_LIST_REMOVE_CURRENT(entry); 00981 break; 00982 } 00983 } 00984 AST_LIST_TRAVERSE_SAFE_END; 00985 00986 /* second remove modules from heap sorted by priority */ 00987 while ((mod = ast_heap_pop(resource_heap))) { 00988 switch (start_resource(mod)) { 00989 case AST_MODULE_LOAD_SUCCESS: 00990 count++; 00991 case AST_MODULE_LOAD_DECLINE: 00992 break; 00993 case AST_MODULE_LOAD_FAILURE: 00994 res = -1; 00995 goto done; 00996 case AST_MODULE_LOAD_SKIP: 00997 case AST_MODULE_LOAD_PRIORITY: 00998 break; 00999 } 01000 } 01001 01002 done: 01003 if (mod_count) { 01004 *mod_count += count; 01005 } 01006 ast_heap_destroy(resource_heap); 01007 01008 return res; 01009 }
static int mod_load_cmp | ( | void * | a, | |
void * | b | |||
) | [static] |
Definition at line 932 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().
00933 { 00934 struct ast_module *a_mod = (struct ast_module *) a; 00935 struct ast_module *b_mod = (struct ast_module *) b; 00936 int res = -1; 00937 /* if load_pri is not set, default is 128. Lower is better*/ 00938 unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128; 00939 unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128; 00940 if (a_pri == b_pri) { 00941 res = 0; 00942 } else if (a_pri < b_pri) { 00943 res = 1; 00944 } 00945 return res; 00946 }
static int printdigest | ( | const unsigned char * | d | ) | [static] |
Definition at line 282 of file loader.c.
References ast_debug.
Referenced by verify_key().
00283 { 00284 int x, pos; 00285 char buf[256]; /* large enough so we don't have to worry */ 00286 00287 for (pos = 0, x = 0; x < 16; x++) 00288 pos += sprintf(buf + pos, " %02x", *d++); 00289 00290 ast_debug(1, "Unexpected signature:%s\n", buf); 00291 00292 return 0; 00293 }
static void queue_reload_request | ( | const char * | module | ) | [static] |
Definition at line 637 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, ast_module_user::entry, LOG_ERROR, and reload_queue_item::module.
Referenced by ast_module_reload().
00638 { 00639 struct reload_queue_item *item; 00640 00641 AST_LIST_LOCK(&reload_queue); 00642 00643 if (do_full_reload) { 00644 AST_LIST_UNLOCK(&reload_queue); 00645 return; 00646 } 00647 00648 if (ast_strlen_zero(module)) { 00649 /* A full reload request (when module is NULL) wipes out any previous 00650 reload requests and causes the queue to ignore future ones */ 00651 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) { 00652 ast_free(item); 00653 } 00654 do_full_reload = 1; 00655 } else { 00656 /* No reason to add the same module twice */ 00657 AST_LIST_TRAVERSE(&reload_queue, item, entry) { 00658 if (!strcasecmp(item->module, module)) { 00659 AST_LIST_UNLOCK(&reload_queue); 00660 return; 00661 } 00662 } 00663 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1); 00664 if (!item) { 00665 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n"); 00666 AST_LIST_UNLOCK(&reload_queue); 00667 return; 00668 } 00669 strcpy(item->module, module); 00670 AST_LIST_INSERT_TAIL(&reload_queue, item, entry); 00671 } 00672 AST_LIST_UNLOCK(&reload_queue); 00673 }
static int resource_name_match | ( | const char * | name1_in, | |
const char * | name2_in | |||
) | [static] |
Definition at line 324 of file loader.c.
References ast_strdupa.
Referenced by add_to_load_order(), ast_module_reload(), and find_resource().
00325 { 00326 char *name1 = (char *) name1_in; 00327 char *name2 = (char *) name2_in; 00328 00329 /* trim off any .so extensions */ 00330 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) { 00331 name1 = ast_strdupa(name1); 00332 name1[strlen(name1) - 3] = '\0'; 00333 } 00334 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) { 00335 name2 = ast_strdupa(name2); 00336 name2[strlen(name2) - 3] = '\0'; 00337 } 00338 00339 return strcasecmp(name1, name2); 00340 }
static enum ast_module_load_result start_resource | ( | struct ast_module * | mod | ) | [static] |
Definition at line 791 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().
00792 { 00793 char tmp[256]; 00794 enum ast_module_load_result res; 00795 00796 if (!mod->info->load) { 00797 return AST_MODULE_LOAD_FAILURE; 00798 } 00799 00800 res = mod->info->load(); 00801 00802 switch (res) { 00803 case AST_MODULE_LOAD_SUCCESS: 00804 if (!ast_fully_booted) { 00805 ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00806 if (ast_opt_console && !option_verbose) 00807 ast_verbose( "."); 00808 } else { 00809 ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description); 00810 } 00811 00812 mod->flags.running = 1; 00813 00814 ast_update_use_count(); 00815 break; 00816 case AST_MODULE_LOAD_DECLINE: 00817 mod->flags.declined = 1; 00818 break; 00819 case AST_MODULE_LOAD_FAILURE: 00820 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */ 00821 case AST_MODULE_LOAD_PRIORITY: 00822 break; 00823 } 00824 00825 return res; 00826 }
static void unload_dynamic_module | ( | struct ast_module * | mod | ) | [static] |
Definition at line 361 of file loader.c.
References ast_module::lib.
Referenced by ast_unload_resource(), and load_resource().
00362 { 00363 void *lib = mod->lib; 00364 00365 /* WARNING: the structure pointed to by mod is going to 00366 disappear when this operation succeeds, so we can't 00367 dereference it */ 00368 00369 if (lib) 00370 while (!dlclose(lib)); 00371 }
static int verify_key | ( | const unsigned char * | key | ) | [static] |
Definition at line 307 of file loader.c.
References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().
Referenced by inspect_module().
00308 { 00309 struct MD5Context c; 00310 unsigned char digest[16]; 00311 00312 MD5Init(&c); 00313 MD5Update(&c, key, strlen((char *)key)); 00314 MD5Final(digest, &c); 00315 00316 if (key_matches(expected_key, digest)) 00317 return 0; 00318 00319 printdigest(digest); 00320 00321 return -1; 00322 }
char buildopt_sum[33] = AST_BUILDOPT_SUM [static] |
int do_full_reload = 0 [static] |
Definition at line 134 of file loader.c.
Referenced by ast_process_pending_reloads(), and queue_reload_request().
struct module_list embedded_module_list [static] |
unsigned int embedding = 1 [static] |
const unsigned char expected_key[] [static] |
Initial value:
{ 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3, 0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 }
Definition at line 78 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] |