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