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