Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Macros | Functions | Variables
loader.c File Reference

Module Loader. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <dirent.h>
#include "asterisk/dlinkedlists.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/io.h"
#include "asterisk/lock.h"
#include "asterisk/vector.h"
#include "asterisk/app.h"
#include "asterisk/test.h"
#include "asterisk/cli.h"
#include <dlfcn.h>
#include "asterisk/md5.h"
#include "asterisk/utils.h"
Include dependency graph for loader.c:

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  load_results_map
 
struct  load_retries
 
struct  loadupdate
 
struct  module_list
 
struct  module_load_word
 
struct  module_user_list
 
struct  module_vector
 
struct  reload_queue
 
struct  reload_queue_item
 
struct  updaters
 

Macros

#define AST_MODULE_LOAD_UNKNOWN_STRING   "Unknown" /* Status string for unknown load status */
 
#define key_matches(a, b)   (memcmp((a), (b), 16) == 0)
 
#define RTLD_LOCAL   0
 
#define RTLD_NOW   0
 
#define STR_APPEND_TEXT(txt, str)
 

Functions

struct ast_module__ast_module_ref (struct ast_module *mod, const char *file, int line, const char *func)
 
struct ast_module__ast_module_running_ref (struct ast_module *mod, const char *file, int line, const char *func)
 
void __ast_module_shutdown_ref (struct ast_module *mod, const char *file, int line, const char *func)
 
void __ast_module_unref (struct ast_module *mod, const char *file, int line, const char *func)
 
struct ast_module_user__ast_module_user_add (struct ast_module *mod, struct ast_channel *chan)
 
void __ast_module_user_hangup_all (struct ast_module *mod)
 
void __ast_module_user_remove (struct ast_module *mod, struct ast_module_user *u)
 
static struct load_order_entryadd_to_load_order (const char *resource, struct load_order *load_order, int required, int preload, int builtin)
 
static int alpha_module_list_create (struct module_vector *alpha_module_list)
 
enum ast_module_load_result ast_load_resource (const char *resource_name)
 Load a module. More...
 
int ast_loader_register (int(*v)(void))
 Add a procedure to be run when modules have been updated. More...
 
int ast_loader_unregister (int(*v)(void))
 Remove a procedure to be run when modules are updated. More...
 
int ast_module_check (const char *name)
 Check if module exists. More...
 
char * ast_module_helper (const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type)
 Match modules names for the Asterisk cli. More...
 
const char * ast_module_name (const struct ast_module *mod)
 Get the name of a module. More...
 
void ast_module_register (const struct ast_module_info *info)
 
enum ast_module_reload_result ast_module_reload (const char *name)
 Reload asterisk modules. More...
 
const char * ast_module_support_level_to_string (enum ast_module_support_level support_level)
 
void ast_module_unregister (const struct ast_module_info *info)
 
void ast_process_pending_reloads (void)
 Process reload requests received during startup. More...
 
int ast_refresh_resource (const char *resource_name, enum ast_module_unload_mode force, int recursive)
 Unload and load a module again. More...
 
int ast_unload_resource (const char *resource_name, enum ast_module_unload_mode force)
 Unload a module. More...
 
int ast_update_module_list (int(*modentry)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level), const char *like)
 Ask for a list of modules, descriptions, use counts and status. More...
 
int ast_update_module_list_condition (int(*modentry)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level, void *data, const char *condition), const char *like, void *data, const char *condition)
 Ask for a list of modules, descriptions, use counts and status. More...
 
int ast_update_module_list_data (int(*modentry)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level, void *data), const char *like, void *data)
 Ask for a list of modules, descriptions, use counts and status. More...
 
void ast_update_use_count (void)
 Notify when usecount has been changed. More...
 
static int auto_unload_resource (const char *resource_name, enum ast_module_unload_mode force, int recursive, struct ast_vector_const_string *dependents)
 Unload a resource. More...
 
static struct ast_modulefind_resource (const char *resource, int do_lock)
 
static char * get_name_from_resource (const char *resource)
 
static int graceful_unload_possible (struct ast_module *target, struct ast_vector_const_string *dependents)
 Whether or not this module should be able to be unloaded successfully, if we recursively unload any modules that are dependent on it. More...
 
static unsigned int inspect_module (const struct ast_module *mod)
 
static int is_module_loaded (const char *resource_name)
 Check to see if the given resource is loaded. More...
 
static struct ast_moduleload_dlopen (const char *resource_in, const char *so_ext, const char *filename, int flags, unsigned int suppress_logging)
 
static int load_dlopen_missing (struct ast_str **list, struct ast_vector_string *deps)
 
static struct ast_moduleload_dynamic_module (const char *resource_in, unsigned int suppress_logging)
 
int load_modules (void)
 
static enum ast_module_load_result load_resource (const char *resource_name, unsigned int suppress_logging, struct module_vector *module_priorities, int required, int preload)
 
static int load_resource_list (struct load_order *load_order, int *mod_count)
 
static int loader_builtin_init (struct load_order *load_order)
 
static int loader_config_init (struct load_order *load_order)
 
static const char * loadresult2str (enum ast_module_load_result result)
 
static void logged_dlclose (const char *name, void *lib)
 dlclose(), with failure logging. More...
 
static int module_deps_missing_recursive (struct ast_module *mod, struct module_vector *missingdeps)
 Recursively find required dependencies that are not running. More...
 
static int module_deps_process_reqlist (struct ast_module *mod, struct ast_vector_string *vec, struct ast_vector_const_string *missing, int ref_enhancers, int isoptional)
 
static int module_deps_reference (struct ast_module *mod, struct ast_vector_const_string *missing)
 
static void module_destroy (struct ast_module *mod)
 
static void module_load_error (const char *fmt,...)
 
static void module_load_helper (const char *word)
 
static int module_load_helper_on_file (const char *dir_name, const char *filename, void *obj)
 
static int module_matches_helper_type (struct ast_module *mod, enum ast_module_helper_type type)
 
static int module_post_register (struct ast_module *mod)
 
static int module_reffed_deps_add (struct ast_module *mod, struct ast_module *dep, struct ast_vector_const_string *missing)
 
static int module_reffed_deps_add_dep_enhancers (struct ast_module *mod, struct ast_module *dep, struct ast_vector_const_string *missing)
 
static int module_vector_cmp (struct ast_module *a, struct ast_module *b)
 
static int module_vector_strcasecmp (struct ast_module *a, struct ast_module *b)
 
int modules_shutdown (void)
 
static int printdigest (const unsigned char *d)
 
static void publish_load_message (const char *name, enum ast_module_load_result result)
 
static void publish_load_message_type (const char *type, const char *name, const char *status)
 
static void publish_reload_message (const char *name, enum ast_module_reload_result result)
 
static void publish_unload_message (const char *name, const char *status)
 
static void queue_reload_request (const char *module)
 
static int resource_list_recursive_decline (struct module_vector *resources, struct ast_module *mod, struct ast_str **printmissing)
 
static size_t resource_name_baselen (const char *name)
 
static int resource_name_match (const char *name1, size_t baselen1, const char *name2)
 
static enum ast_module_load_result start_resource (struct ast_module *mod)
 
static enum ast_module_load_result start_resource_attempt (struct ast_module *mod, int *count)
 
static int start_resource_list (struct module_vector *resources, int *mod_count)
 
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 struct module_list builtin_module_list
 
static int do_full_reload = 0
 
static const unsigned char expected_key []
 
static const struct load_results_map load_results []
 
static unsigned int loader_ready
 
static struct module_list module_list = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static int modules_loaded
 Internal flag to indicate all modules have been initially loaded. More...
 
static struct reload_queue reload_queue = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static ast_mutex_t reloadlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static struct ast_module *volatile resource_being_loaded
 
static struct ast_strstartup_error_builder
 
static struct ast_vector_string startup_errors
 
const char * support_level_map []
 
static struct updaters updaters = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 

Detailed Description

Module Loader.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Kevin P. Fleming kpfle.nosp@m.ming.nosp@m.@digi.nosp@m.um.c.nosp@m.om
Luigi Rizzo rizzo.nosp@m.@ici.nosp@m.r.org
  • See ModMngMnt

Definition in file loader.c.

Macro Definition Documentation

◆ AST_MODULE_LOAD_UNKNOWN_STRING

#define AST_MODULE_LOAD_UNKNOWN_STRING   "Unknown" /* Status string for unknown load status */

Definition at line 360 of file loader.c.

◆ key_matches

#define key_matches (   a,
  b 
)    (memcmp((a), (b), 16) == 0)

Definition at line 897 of file loader.c.

◆ RTLD_LOCAL

#define RTLD_LOCAL   0

Definition at line 133 of file loader.c.

◆ RTLD_NOW

#define RTLD_NOW   0

Definition at line 129 of file loader.c.

◆ STR_APPEND_TEXT

#define STR_APPEND_TEXT (   txt,
  str 
)
Value:
ast_str_append(str, 0, "%s%s", \
ast_str_strlen(*(str)) > 0 ? ", " : "", \
txt)
const char * str
Definition: app_jack.c:150
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730

Used with AST_VECTOR_CALLBACK_VOID to create a comma separated list of module names for error messages.

Definition at line 153 of file loader.c.

Function Documentation

◆ __ast_module_ref()

struct ast_module * __ast_module_ref ( struct ast_module mod,
const char *  file,
int  line,
const char *  func 
)

Definition at line 2877 of file loader.c.

2878{
2879 if (!mod) {
2880 return NULL;
2881 }
2882
2883 if (mod->ref_debug) {
2884 __ao2_ref(mod->ref_debug, +1, "", file, line, func);
2885 }
2886
2889
2890 return mod;
2891}
int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func)
Definition: astobj2.c:498
void ast_update_use_count(void)
Notify when usecount has been changed.
Definition: loader.c:2707
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:761
#define NULL
Definition: resample.c:96
void * ref_debug
Definition: loader.c:305
int usecount
Definition: loader.c:309

References __ao2_ref(), ast_atomic_fetchadd_int(), ast_update_use_count(), make_ari_stubs::file, NULL, ast_module::ref_debug, and ast_module::usecount.

Referenced by __ast_module_running_ref(), and __ast_module_shutdown_ref().

◆ __ast_module_running_ref()

struct ast_module * __ast_module_running_ref ( struct ast_module mod,
const char *  file,
int  line,
const char *  func 
)

Definition at line 2893 of file loader.c.

2895{
2896 if (!mod || !mod->flags.running) {
2897 return NULL;
2898 }
2899
2900 return __ast_module_ref(mod, file, line, func);
2901}
struct ast_module * __ast_module_ref(struct ast_module *mod, const char *file, int line, const char *func)
Definition: loader.c:2877
unsigned int running
Definition: loader.c:329
struct ast_module::@365 flags

References __ast_module_ref(), make_ari_stubs::file, ast_module::flags, NULL, and ast_module::running.

◆ __ast_module_shutdown_ref()

void __ast_module_shutdown_ref ( struct ast_module mod,
const char *  file,
int  line,
const char *  func 
)

Definition at line 2903 of file loader.c.

2904{
2905 if (!mod || mod->flags.keepuntilshutdown) {
2906 return;
2907 }
2908
2909 __ast_module_ref(mod, file, line, func);
2910 mod->flags.keepuntilshutdown = 1;
2911}
unsigned int keepuntilshutdown
Definition: loader.c:333

References __ast_module_ref(), make_ari_stubs::file, ast_module::flags, and ast_module::keepuntilshutdown.

◆ __ast_module_unref()

void __ast_module_unref ( struct ast_module mod,
const char *  file,
int  line,
const char *  func 
)

Definition at line 2913 of file loader.c.

2914{
2915 if (!mod) {
2916 return;
2917 }
2918
2919 if (mod->ref_debug) {
2920 __ao2_ref(mod->ref_debug, -1, "", file, line, func);
2921 }
2922
2925}

References __ao2_ref(), ast_atomic_fetchadd_int(), ast_update_use_count(), make_ari_stubs::file, ast_module::ref_debug, and ast_module::usecount.

◆ __ast_module_user_add()

struct ast_module_user * __ast_module_user_add ( struct ast_module mod,
struct ast_channel chan 
)

Definition at line 809 of file loader.c.

810{
811 struct ast_module_user *u;
812
813 u = ast_calloc(1, sizeof(*u));
814 if (!u) {
815 return NULL;
816 }
817
818 u->chan = chan;
819
820 AST_LIST_LOCK(&mod->users);
822 AST_LIST_UNLOCK(&mod->users);
823
824 if (mod->ref_debug) {
825 ao2_ref(mod->ref_debug, +1);
826 }
827
829
831
832 return u;
833}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
struct ast_module_user::@364 entry
struct ast_channel * chan
Definition: loader.c:137
struct module_user_list users
Definition: loader.c:311

References ao2_ref, 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, NULL, ast_module::ref_debug, ast_module::usecount, and ast_module::users.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and pbx_exec().

◆ __ast_module_user_hangup_all()

void __ast_module_user_hangup_all ( struct ast_module mod)

Definition at line 862 of file loader.c.

863{
864 struct ast_module_user *u;
865
866 AST_LIST_LOCK(&mod->users);
867 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
868 if (u->chan) {
870 }
871
872 if (mod->ref_debug) {
873 ao2_ref(mod->ref_debug, -1);
874 }
875
877 ast_free(u);
878 }
879 AST_LIST_UNLOCK(&mod->users);
880
882}
#define ast_free(a)
Definition: astmm.h:180
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2500
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1163
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833

References ao2_ref, 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::ref_debug, ast_module::usecount, and ast_module::users.

Referenced by auto_unload_resource().

◆ __ast_module_user_remove()

void __ast_module_user_remove ( struct ast_module mod,
struct ast_module_user u 
)

Definition at line 835 of file loader.c.

836{
837 if (!u) {
838 return;
839 }
840
841 AST_LIST_LOCK(&mod->users);
842 u = AST_LIST_REMOVE(&mod->users, u, entry);
843 AST_LIST_UNLOCK(&mod->users);
844 if (!u) {
845 /*
846 * Was not in the list. Either a bad pointer or
847 * __ast_module_user_hangup_all() has been called.
848 */
849 return;
850 }
851
852 if (mod->ref_debug) {
853 ao2_ref(mod->ref_debug, -1);
854 }
855
857 ast_free(u);
858
860}
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856

References ao2_ref, 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::ref_debug, ast_module::usecount, and ast_module::users.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and pbx_exec().

◆ add_to_load_order()

static struct load_order_entry * add_to_load_order ( const char *  resource,
struct load_order load_order,
int  required,
int  preload,
int  builtin 
)
static

Definition at line 2021 of file loader.c.

2022{
2023 struct load_order_entry *order;
2024 size_t resource_baselen = resource_name_baselen(resource);
2025
2027 if (!resource_name_match(resource, resource_baselen, order->resource)) {
2028 /* Make sure we have the proper setting for the required field
2029 (we might have both load= and required= lines in modules.conf) */
2030 order->required |= required;
2031 order->preload |= preload;
2032 return order;
2033 }
2034 }
2035
2036 order = ast_calloc(1, sizeof(*order));
2037 if (!order) {
2038 return NULL;
2039 }
2040
2041 order->resource = ast_strdup(resource);
2042 if (!order->resource) {
2043 ast_free(order);
2044
2045 return NULL;
2046 }
2047 order->required = required;
2048 order->preload = preload;
2049 order->builtin = builtin;
2051
2052 return order;
2053}
integer order
Definition: analys.c:66
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
static int resource_name_match(const char *name1, size_t baselen1, const char *name2)
Definition: loader.c:927
static size_t resource_name_baselen(const char *name)
Definition: loader.c:916
Definition: loader.c:2011
int builtin
Definition: loader.c:2015
int required
Definition: loader.c:2013
int preload
Definition: loader.c:2014
char * resource
Definition: loader.c:2012
struct load_order_entry::@369 entry

References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, load_order_entry::builtin, load_order_entry::entry, NULL, order, load_order_entry::preload, load_order_entry::required, load_order_entry::resource, resource_name_baselen(), and resource_name_match().

Referenced by loader_builtin_init(), and loader_config_init().

◆ alpha_module_list_create()

static int alpha_module_list_create ( struct module_vector alpha_module_list)
static

Definition at line 2729 of file loader.c.

2730{
2731 struct ast_module *cur;
2732
2733 if (AST_VECTOR_INIT(alpha_module_list, 32)) {
2734 return -1;
2735 }
2736
2738 if (AST_VECTOR_ADD_SORTED(alpha_module_list, cur, module_vector_strcasecmp)) {
2739 return -1;
2740 }
2741 }
2742
2743 return 0;
2744}
#define AST_DLLIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: dlinkedlists.h:576
static int module_vector_strcasecmp(struct ast_module *a, struct ast_module *b)
Definition: loader.c:375
struct ast_module::@366 entry
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:371
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References AST_DLLIST_TRAVERSE, AST_VECTOR_ADD_SORTED, AST_VECTOR_INIT, ast_module::entry, and module_vector_strcasecmp().

Referenced by ast_update_module_list(), ast_update_module_list_condition(), and ast_update_module_list_data().

◆ ast_load_resource()

enum ast_module_load_result ast_load_resource ( const char *  resource_name)

Load a module.

Parameters
resource_nameThe name of the module to load.

This function is run by the PBX to load the modules. It performs all loading and initialization tasks. Basically, to load a module, just give it the name of the module and it will do the rest.

Returns
See possible enum values for ast_module_load_result.

Definition at line 1987 of file loader.c.

1988{
1989 struct ast_module *mod;
1990 enum ast_module_load_result res;
1991
1992 /* If we're trying to load a module that previously declined to load,
1993 * transparently unload it first so we dlclose, then dlopen it afresh.
1994 * Otherwise, we won't actually load a (potentially) updated module. */
1995 mod = find_resource(resource_name, 0);
1996 if (mod && mod->flags.declined) {
1997 ast_debug(1, "Module %s previously declined to load, unloading it first before loading again\n", resource_name);
1998 ast_unload_resource(resource_name, 0);
1999 }
2000
2002 res = load_resource(resource_name, 0, NULL, 0, 0);
2003 if (!res) {
2004 ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);
2005 }
2007
2008 return res;
2009}
#define AST_DLLIST_LOCK(head)
Locks a list.
Definition: dlinkedlists.h:46
#define AST_DLLIST_UNLOCK(head)
Attempts to unlock a list.
Definition: dlinkedlists.h:123
#define ast_debug(level,...)
Log a DEBUG message.
static struct ast_module * find_resource(const char *resource, int do_lock)
Definition: loader.c:936
static enum ast_module_load_result load_resource(const char *resource_name, unsigned int suppress_logging, struct module_vector *module_priorities, int required, int preload)
Definition: loader.c:1931
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
Unload a module.
Definition: loader.c:1457
ast_module_load_result
Definition: module.h:68
unsigned int declined
Definition: loader.c:331
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189

References ast_debug, AST_DLLIST_LOCK, AST_DLLIST_UNLOCK, ast_test_suite_event_notify, ast_unload_resource(), ast_module::declined, find_resource(), ast_module::flags, load_resource(), and NULL.

Referenced by ast_ari_asterisk_load_module(), ast_refresh_resource(), auto_unload_resource(), handle_load(), and manager_moduleload().

◆ ast_loader_register()

int ast_loader_register ( int(*)(void)  updater)

Add a procedure to be run when modules have been updated.

Parameters
updaterThe function to run when modules have been updated.

This function adds the given function to a linked list of functions to be run when the modules are updated.

Return values
0on success
-1on failure.

Definition at line 2845 of file loader.c.

2846{
2847 struct loadupdate *tmp;
2848
2849 if (!(tmp = ast_malloc(sizeof(*tmp))))
2850 return -1;
2851
2852 tmp->updater = v;
2856
2857 return 0;
2858}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
struct loadupdate::@367 entry
int(* updater)(void)
Definition: loader.c:634

◆ ast_loader_unregister()

int ast_loader_unregister ( int(*)(void)  updater)

Remove a procedure to be run when modules are updated.

Parameters
updaterThe updater function to unregister.

This removes the given function from the updater list.

Return values
0on success
-1on failure.

Definition at line 2860 of file loader.c.

2861{
2862 struct loadupdate *cur;
2863
2866 if (cur->updater == v) {
2868 break;
2869 }
2870 }
2873
2874 return cur ? 0 : -1;
2875}
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557

◆ ast_module_check()

int ast_module_check ( const char *  name)

Check if module exists.

Check if module with the name given is loaded.

Definition at line 2832 of file loader.c.

2833{
2834 struct ast_module *cur;
2835
2836 if (ast_strlen_zero(name))
2837 return 0; /* FALSE */
2838
2839 cur = find_resource(name, 1);
2840
2841 return (cur != NULL);
2842}
static const char name[]
Definition: format_mp3.c:68
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References ast_strlen_zero(), find_resource(), name, and NULL.

Referenced by ast_ari_asterisk_get_module(), ast_ari_asterisk_load_module(), ast_ari_asterisk_reload_module(), ast_ari_asterisk_unload_module(), AST_TEST_DEFINE(), ifmodule_read(), load_module(), and manager_modulecheck().

◆ ast_module_helper()

char * ast_module_helper ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos,
enum ast_module_helper_type  type 
)

Match modules names for the Asterisk cli.

Parameters
lineUnused by this function, but this should be the line we are matching.
wordThe partial name to match.
posThe position the word we are completing is in.
stateThe possible match to return.
rposThe position we should be matching. This should be the same as pos.
typeThe type of action that will be performed by CLI.
Return values
Apossible completion of the partial match.
NULLif no matches were found or Asterisk is not yet fully booted.

Definition at line 1537 of file loader.c.

1538{
1539 struct ast_module *mod;
1540 int which = 0;
1541 int wordlen = strlen(word);
1542 char *ret = NULL;
1543
1544 if (pos != rpos) {
1545 return NULL;
1546 }
1547
1548 /* Tab completion can't be used during startup, or CLI and loader will deadlock. */
1550 return NULL;
1551 }
1552
1555
1556 return NULL;
1557 }
1558
1561 if (!module_matches_helper_type(mod, type)) {
1562 continue;
1563 }
1564
1565 if (!strncasecmp(word, mod->resource, wordlen) && ++which > state) {
1566 ret = ast_strdup(mod->resource);
1567 break;
1568 }
1569 }
1571
1572 return ret;
1573}
static const char type[]
Definition: chan_ooh323.c:109
short word
struct ast_flags ast_options
Definition: options.c:61
@ AST_OPT_FLAG_FULLY_BOOTED
Definition: options.h:58
static int module_matches_helper_type(struct ast_module *mod, enum ast_module_helper_type type)
Definition: loader.c:1462
static void module_load_helper(const char *word)
Definition: loader.c:1524
@ AST_MODULE_HELPER_LOAD
Definition: module.h:133
char resource[0]
Definition: loader.c:342
#define ast_test_flag(p, flag)
Definition: utils.h:63

References AST_DLLIST_LOCK, AST_DLLIST_TRAVERSE, AST_DLLIST_UNLOCK, AST_MODULE_HELPER_LOAD, AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_strdup, ast_test_flag, ast_module::entry, module_load_helper(), module_matches_helper_type(), NULL, ast_module::resource, and type.

Referenced by handle_debug(), handle_load(), handle_modlist(), handle_refresh(), handle_reload(), handle_trace(), and handle_unload().

◆ ast_module_name()

const char * ast_module_name ( const struct ast_module mod)

Get the name of a module.

Parameters
modA pointer to the module.
Returns
the name of the module
Return values
NULLif mod or mod->info is NULL

Definition at line 624 of file loader.c.

625{
626 if (!mod || !mod->info) {
627 return NULL;
628 }
629
630 return mod->info->name;
631}
const char * name
Definition: module.h:364
const struct ast_module_info * info
Definition: loader.c:303

References ast_module::info, ast_module_info::name, and NULL.

Referenced by acf_retrieve_docs(), ast_register_application2(), graceful_unload_possible(), resource_list_recursive_decline(), start_resource_list(), and unload_dynamic_module().

◆ ast_module_register()

void ast_module_register ( const struct ast_module_info info)

Definition at line 668 of file loader.c.

669{
670 struct ast_module *mod;
671
672 if (!loader_ready) {
673 mod = ast_std_calloc(1, sizeof(*mod) + strlen(info->name) + 1);
674 if (!mod) {
675 /* We haven't even reached main() yet, if we can't
676 * allocate memory at this point just give up. */
677 fprintf(stderr, "Allocation failure during startup.\n");
678 exit(2);
679 }
680 strcpy(mod->resource, info->name); /* safe */
681 mod->info = info;
682 mod->flags.builtin = 1;
684
685 /* ast_module_register for built-in modules is run again during module preload. */
686 return;
687 }
688
689 /*
690 * This lock protects resource_being_loaded as well as the module
691 * list. Normally we already have a lock on module_list when we
692 * begin the load but locking again from here prevents corruption
693 * if an asterisk module is dlopen'ed from outside the module loader.
694 */
697 if (!mod) {
699 return;
700 }
701
702 ast_debug(5, "Registering module %s\n", info->name);
703
704 /* This tells load_dynamic_module that we're registered. */
706
707 mod->info = info;
708 if (ast_opt_ref_debug) {
710 }
712 AST_VECTOR_INIT(&mod->requires, 0);
714 AST_VECTOR_INIT(&mod->enhances, 0);
716
719
720 /* give the module a copy of its own handle, for later use in registrations and the like */
721 *((struct ast_module **) &(info->self)) = mod;
722
723#if defined(HAVE_PERMANENT_DLOPEN)
724 if (mod->flags.builtin != 1) {
725 struct info_list_obj *obj_tmp = ao2_find(info_list, info->name,
727
728 if (!obj_tmp) {
729 obj_tmp = info_list_obj_alloc(info->name, info);
730 if (obj_tmp) {
731 ao2_link(info_list, obj_tmp);
732 ao2_ref(obj_tmp, -1);
733 }
734 } else {
735 ao2_ref(obj_tmp, -1);
736 }
737 }
738#endif
739}
void * ast_std_calloc(size_t nmemb, size_t size) attribute_malloc
Definition: astmm.c:1724
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:402
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define AST_DLLIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
static unsigned int loader_ready
Definition: loader.c:159
static struct module_list builtin_module_list
Definition: loader.c:373
static struct ast_module *volatile resource_being_loaded
Definition: loader.c:659
def info(msg)
#define ast_opt_ref_debug
Definition: options.h:135
struct ast_vector_string requires
Definition: loader.c:314
struct ast_vector_string optional_modules
Definition: loader.c:316
struct module_vector reffed_deps
Vector holding pointers to modules we have a reference to.
Definition: loader.c:326
unsigned int builtin
Definition: loader.c:335
struct ast_vector_string enhances
Definition: loader.c:318

Referenced by loader_builtin_init().

◆ ast_module_reload()

enum ast_module_reload_result ast_module_reload ( const char *  name)

Reload asterisk modules.

Parameters
namethe name of the module to reload

This function reloads the specified module, or if no modules are specified, it will reload all loaded modules.

Note
Modules are reloaded using their reload() functions, not unloading them and loading them again.
Return values
Theast_module_reload_result status of the module load request

Definition at line 1730 of file loader.c.

1731{
1732 struct ast_module *cur;
1734 size_t name_baselen = name ? resource_name_baselen(name) : 0;
1735
1736 /* If we aren't fully booted, we just pretend we reloaded but we queue this
1737 up to run once we are booted up. */
1738 if (!modules_loaded) {
1741 goto module_reload_exit;
1742 }
1743
1745 ast_verb(3, "The previous reload command didn't finish yet\n");
1747 goto module_reload_exit;
1748 }
1749 ast_sd_notify("RELOADING=1");
1751
1753 int try;
1754 int lockres;
1755 for (try = 1, lockres = AST_LOCK_TIMEOUT; try < 6 && (lockres == AST_LOCK_TIMEOUT); try++) {
1757 if (lockres == AST_LOCK_TIMEOUT) {
1758 ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try);
1759 }
1760 }
1761 if (lockres != AST_LOCK_SUCCESS) {
1762 ast_log(AST_LOG_WARNING, "Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR);
1764 goto module_reload_done;
1765 }
1766 }
1767
1770 const struct ast_module_info *info = cur->info;
1771
1772 if (name && resource_name_match(name, name_baselen, cur->resource)) {
1773 continue;
1774 }
1775
1776 if (!cur->flags.running || cur->flags.declined) {
1777 if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1779 }
1780 if (!name) {
1781 continue;
1782 }
1783 break;
1784 }
1785
1786 if (!info->reload) { /* cannot be reloaded */
1787 if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1789 }
1790 if (!name) {
1791 continue;
1792 }
1793 break;
1794 }
1795 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
1796 if (info->reload() == AST_MODULE_LOAD_SUCCESS) {
1798 } else if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1800 }
1801 if (name) {
1802 break;
1803 }
1804 }
1806
1809 }
1810module_reload_done:
1812 ast_sd_notify("READY=1");
1813
1814module_reload_exit:
1816 return res;
1817}
#define ast_log
Definition: astobj2.c:42
@ AST_LOCK_SUCCESS
@ AST_LOCK_TIMEOUT
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2614
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2630
#define AST_LOG_WARNING
#define ast_verb(level,...)
#define LOG_WARNING
int ast_sd_notify(const char *state)
a wrapper for sd_notify(): notify systemd of any state changes.
Definition: io.c:392
static int modules_loaded
Internal flag to indicate all modules have been initially loaded.
Definition: loader.c:300
static ast_mutex_t reloadlock
Definition: loader.c:640
static void queue_reload_request(const char *module)
Definition: loader.c:1600
static void publish_reload_message(const char *name, enum ast_module_reload_result result)
Definition: loader.c:1722
#define ast_mutex_unlock(a)
Definition: lock.h:194
#define ast_mutex_trylock(a)
Definition: lock.h:195
ast_module_reload_result
Possible return types for ast_module_reload.
Definition: module.h:109
@ AST_MODULE_RELOAD_IN_PROGRESS
Definition: module.h:114
@ AST_MODULE_RELOAD_QUEUED
Definition: module.h:111
@ AST_MODULE_RELOAD_SUCCESS
Definition: module.h:110
@ AST_MODULE_RELOAD_ERROR
Definition: module.h:113
@ AST_MODULE_RELOAD_NOT_IMPLEMENTED
Definition: module.h:116
@ AST_MODULE_RELOAD_NOT_FOUND
Definition: module.h:112
@ AST_MODULE_RELOAD_UNINITIALIZED
Definition: module.h:115
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define ast_opt_lock_confdir
Definition: options.h:133
struct timeval ast_lastreloadtime
Definition: asterisk.c:343
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ast_config_AST_CONFIG_DIR, AST_DLLIST_LOCK, AST_DLLIST_TRAVERSE, AST_DLLIST_UNLOCK, ast_lastreloadtime, ast_lock_path(), AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log, AST_LOG_WARNING, AST_MODULE_LOAD_SUCCESS, AST_MODULE_RELOAD_ERROR, AST_MODULE_RELOAD_IN_PROGRESS, AST_MODULE_RELOAD_NOT_FOUND, AST_MODULE_RELOAD_NOT_IMPLEMENTED, AST_MODULE_RELOAD_QUEUED, AST_MODULE_RELOAD_SUCCESS, AST_MODULE_RELOAD_UNINITIALIZED, ast_mutex_trylock, ast_mutex_unlock, ast_opt_lock_confdir, ast_sd_notify(), ast_tvnow(), ast_unlock_path(), ast_verb, ast_module::declined, ast_module::entry, ast_module::flags, sip_to_pjsip::info(), ast_module::info, LOG_WARNING, modules_loaded, name, publish_reload_message(), queue_reload_request(), reloadlock, ast_module::resource, resource_name_baselen(), resource_name_match(), and ast_module::running.

Referenced by action_reload(), action_updateconfig(), ast_ari_asterisk_reload_module(), ast_process_pending_reloads(), handle_cli_ael_reload(), handle_cli_moh_reload(), handle_core_reload(), handle_reload(), manager_moduleload(), monitor_sig_flags(), and reload_exec().

◆ ast_module_support_level_to_string()

const char * ast_module_support_level_to_string ( enum ast_module_support_level  support_level)

Definition at line 2934 of file loader.c.

2935{
2936 return support_level_map[support_level];
2937}
const char * support_level_map[]
Definition: loader.c:2927

References support_level_map.

Referenced by identify_module(), modlist_modentry(), and process_module_list().

◆ ast_module_unregister()

void ast_module_unregister ( const struct ast_module_info info)

Definition at line 777 of file loader.c.

778{
779 struct ast_module *mod = NULL;
780
781 /* it is assumed that the users list in the module structure
782 will already be empty, or we cannot have gotten to this
783 point
784 */
787 if (mod->info == info) {
789 break;
790 }
791 }
794
795 if (mod && !mod->usecount) {
796 /*
797 * We are intentionally leaking mod if usecount is not zero.
798 * This is necessary if the module is being forcefully unloaded.
799 * In addition module_destroy is not safe to run after exit()
800 * is called. ast_module_unregister is run during cleanup of
801 * the process when libc releases each module's shared object
802 * library.
803 */
804 ast_debug(5, "Unregistering module %s\n", info->name);
805 module_destroy(mod);
806 }
807}
#define AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: dlinkedlists.h:888
#define AST_DLLIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: dlinkedlists.h:753
#define AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END
Closes a safe loop traversal block.
Definition: dlinkedlists.h:921
static void module_destroy(struct ast_module *mod)
Definition: loader.c:753

◆ ast_process_pending_reloads()

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.

Note
This function will do nothing if the server has not completely started up. Once called, the reload queue is emptied, and further invocations will have no affect.

Definition at line 1575 of file loader.c.

1576{
1577 struct reload_queue_item *item;
1578
1579 modules_loaded = 1;
1580
1582
1583 if (do_full_reload) {
1584 do_full_reload = 0;
1586 ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
1588 return;
1589 }
1590
1592 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
1593 ast_module_reload(item->module);
1594 ast_free(item);
1595 }
1596
1598}
#define LOG_NOTICE
static int do_full_reload
Definition: loader.c:647
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
Definition: loader.c:1730
struct reload_queue_item::@368 entry
static struct aco_type item
Definition: test_config.c:1463

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log, ast_module_reload(), do_full_reload, reload_queue_item::entry, item, LOG_NOTICE, modules_loaded, and NULL.

Referenced by asterisk_daemon().

◆ ast_refresh_resource()

int ast_refresh_resource ( const char *  resource_name,
enum ast_module_unload_mode  force,
int  recursive 
)

Unload and load a module again.

Parameters
resource_nameThe name of the module to unload.
ast_module_unload_modeThe force flag. This should be set using one of the AST_FORCE flags.
recursiveAttempt to recursively unload any dependents of this module if that will allow the module to unload, and load them back again afterwards.
Return values
0on success.
1on error unloading modules.
-1on error loading modules back.

Definition at line 1416 of file loader.c.

1417{
1418 if (recursive) {
1419 /* Recursively unload dependents of this module and then load them back again */
1420 int res, i;
1421 struct ast_vector_const_string dependents;
1422 AST_VECTOR_INIT(&dependents, 0);
1423 res = auto_unload_resource(resource_name, force, recursive, &dependents);
1424 if (res) {
1425 AST_VECTOR_FREE(&dependents);
1426 return 1;
1427 }
1428 /* Start by loading the target again. */
1429 if (ast_load_resource(resource_name)) {
1430 ast_log(LOG_WARNING, "Failed to load module '%s' again automatically\n", resource_name);
1431 AST_VECTOR_FREE(&dependents);
1432 return -1;
1433 }
1434 res = 0;
1435 /* Finally, load again any modules we had to unload in order to refresh the target.
1436 * We must load modules in the reverse order that we unloaded them,
1437 * to preserve dependency requirements. */
1438 for (i = 0; i < AST_VECTOR_SIZE(&dependents); i++) {
1439 const char *depname = AST_VECTOR_GET(&dependents, i);
1440 int mres = ast_load_resource(depname);
1441 if (mres) {
1442 ast_log(LOG_WARNING, "Could not load module '%s' again automatically\n", depname);
1443 }
1444 res |= mres;
1445 }
1446 AST_VECTOR_FREE(&dependents);
1447 return res ? -1 : 0;
1448 }
1449
1450 /* Simple case: just unload and load the module again */
1451 if (ast_unload_resource(resource_name, force)) {
1452 return 1;
1453 }
1454 return ast_load_resource(resource_name);
1455}
static int auto_unload_resource(const char *resource_name, enum ast_module_unload_mode force, int recursive, struct ast_vector_const_string *dependents)
Unload a resource.
Definition: loader.c:1294
enum ast_module_load_result ast_load_resource(const char *resource_name)
Load a module.
Definition: loader.c:1987
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References ast_load_resource(), ast_log, ast_unload_resource(), AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_SIZE, auto_unload_resource(), and LOG_WARNING.

Referenced by handle_refresh(), and manager_moduleload().

◆ ast_unload_resource()

int ast_unload_resource ( const char *  resource_name,
enum  ast_module_unload_mode 
)

Unload a module.

Parameters
resource_nameThe name of the module to unload.
ast_module_unload_modeThe force flag. This should be set using one of the AST_FORCE flags.

This function unloads a module. It will only unload modules that are not in use (usecount not zero), unless AST_FORCE_FIRM or AST_FORCE_HARD is specified. Setting AST_FORCE_FIRM or AST_FORCE_HARD will unload the module regardless of consequences (NOT RECOMMENDED).

Return values
0on success.
-1on error.

Definition at line 1457 of file loader.c.

1458{
1459 return auto_unload_resource(resource_name, force, 0, NULL);
1460}

References auto_unload_resource(), and NULL.

Referenced by ast_ari_asterisk_unload_module(), ast_load_resource(), ast_refresh_resource(), auto_unload_resource(), handle_unload(), manager_moduleload(), and unload_module().

◆ ast_update_module_list()

int ast_update_module_list ( int(*)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level)  modentry,
const char *  like 
)

Ask for a list of modules, descriptions, use counts and status.

Parameters
modentryA 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.

Returns
the number of modules loaded

Definition at line 2746 of file loader.c.

2750{
2751 int total_mod_loaded = 0;
2752 struct module_vector alpha_module_list;
2753
2755
2756 if (!alpha_module_list_create(&alpha_module_list)) {
2757 int idx;
2758
2759 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2760 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2761
2762 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
2763 cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
2764 }
2765 }
2766
2768 AST_VECTOR_FREE(&alpha_module_list);
2769
2770 return total_mod_loaded;
2771}
static int alpha_module_list_create(struct module_vector *alpha_module_list)
Definition: loader.c:2729
enum ast_module_support_level support_level
Definition: module.h:430
const char * description
Definition: module.h:366

References alpha_module_list_create(), AST_DLLIST_LOCK, AST_DLLIST_UNLOCK, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_SIZE, ast_module_info::description, ast_module::flags, ast_module::info, ast_module::resource, ast_module::running, ast_module_info::support_level, and ast_module::usecount.

Referenced by ast_var_Modules(), and handle_modlist().

◆ ast_update_module_list_condition()

int ast_update_module_list_condition ( int(*)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level, void *data, const char *condition)  modentry,
const char *  like,
void *  data,
const char *  condition 
)

Ask for a list of modules, descriptions, use counts and status.

Parameters
modentryA callback to an updater function
like
dataData passed into the callback for manipulation
conditionThe condition to meet

For each of the modules loaded, modentry will be executed with the resource, description, and usecount values of each particular module.

Returns
the number of conditions met
Since
13.5.0

Definition at line 2801 of file loader.c.

2807{
2808 int conditions_met = 0;
2809 struct module_vector alpha_module_list;
2810
2812
2813 if (!alpha_module_list_create(&alpha_module_list)) {
2814 int idx;
2815
2816 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2817 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2818
2819 conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
2820 cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
2821 condition);
2822 }
2823 }
2824
2826 AST_VECTOR_FREE(&alpha_module_list);
2827
2828 return conditions_met;
2829}

References alpha_module_list_create(), AST_DLLIST_LOCK, AST_DLLIST_UNLOCK, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_SIZE, ast_module_info::description, ast_module::flags, ast_module::info, ast_module::resource, ast_module::running, ast_module_info::support_level, and ast_module::usecount.

Referenced by ast_ari_asterisk_get_module().

◆ ast_update_module_list_data()

int ast_update_module_list_data ( int(*)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level, void *data)  modentry,
const char *  like,
void *  data 
)

Ask for a list of modules, descriptions, use counts and status.

Parameters
modentryA callback to an updater function
like
dataData passed into the callback for manipulation

For each of the modules loaded, modentry will be executed with the resource, description, and usecount values of each particular module.

Returns
the number of modules loaded
Since
13.5.0

Definition at line 2773 of file loader.c.

2778{
2779 int total_mod_loaded = 0;
2780 struct module_vector alpha_module_list;
2781
2783
2784 if (!alpha_module_list_create(&alpha_module_list)) {
2785 int idx;
2786
2787 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2788 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2789
2790 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
2791 cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
2792 }
2793 }
2794
2796 AST_VECTOR_FREE(&alpha_module_list);
2797
2798 return total_mod_loaded;
2799}

References alpha_module_list_create(), AST_DLLIST_LOCK, AST_DLLIST_UNLOCK, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_SIZE, ast_module_info::description, ast_module::flags, ast_module::info, ast_module::resource, ast_module::running, ast_module_info::support_level, and ast_module::usecount.

Referenced by ast_ari_asterisk_list_modules().

◆ ast_update_use_count()

void ast_update_use_count ( void  )

Notify when usecount has been changed.

This function calculates use counts and notifies anyone trying to keep track of them. It should be called whenever your module's usecount changes.

Note
The ast_module_user_* functions take care of calling this function for you.

Definition at line 2707 of file loader.c.

2708{
2709 /* Notify any module monitors that the use count for a
2710 resource has changed */
2711 struct loadupdate *m;
2712
2715 m->updater();
2717}

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, loadupdate::entry, and loadupdate::updater.

Referenced by __ast_module_ref(), __ast_module_unref(), __ast_module_user_add(), __ast_module_user_hangup_all(), __ast_module_user_remove(), auto_unload_resource(), ooh323_hangup(), ooh323_new(), ooh323c_call_thread(), start_resource(), and unistim_new().

◆ auto_unload_resource()

static int auto_unload_resource ( const char *  resource_name,
enum ast_module_unload_mode  force,
int  recursive,
struct ast_vector_const_string dependents 
)
static

Unload a resource.

Parameters
resource_nameModule name
force
recursiveWhether to attempt to recursively unload dependents of this module and load them again afterwards
dependents.Can be NULL if autounload is 0.
Return values
0on success, -1 on failure

Definition at line 1294 of file loader.c.

1295{
1296 struct ast_module *mod;
1297 int res = -1;
1298 int error = 0;
1299
1301
1302 if (!(mod = find_resource(resource_name, 0))) {
1304 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
1305 return -1;
1306 }
1307
1308 if (!mod->flags.running || mod->flags.declined) {
1309 /* If the user asks to unload a module that didn't load, obey.
1310 * Otherwise, we never dlclose() modules that fail to load,
1311 * which means if the module (shared object) is updated,
1312 * we can't load the updated module since we never dlclose()'d it.
1313 * Accordingly, obey the unload request so we can load the module
1314 * from scratch next time.
1315 */
1316 ast_log(LOG_NOTICE, "Unloading module '%s' that previously declined to load\n", resource_name);
1317 error = 0;
1318 res = 0;
1319 goto exit; /* Skip all the intervening !error checks, only the last one is relevant. */
1320 }
1321
1322 if (!error && mod->usecount > 0 && recursive) {
1323 /* Try automatically unloading all modules dependent on the module we're trying to unload,
1324 * and then, optionally, load them back again if we end up loading this module again.
1325 * If any modules that have us as a dependency can't be unloaded, for whatever reason,
1326 * then the entire unload operation will fail, so to try to make this an atomic operation
1327 * and avoid leaving modules in a partial unload state, first check if we think we're going
1328 * to be able to pull this off, and if not, abort.
1329 *
1330 * A race condition is technically still possible, if some depending module suddenly goes in use
1331 * between this check and trying to unload it, but this takes care of the majority of
1332 * easy-to-avoid cases that would fail eventually anyways.
1333 *
1334 * Note that we can encounter false negatives (e.g. unloading all the dependents would allow
1335 * a module to unload, but graceful_unload_possible returns 0). This is because it's only
1336 * checking direct module dependencies; other dependencies caused by a module registering
1337 * a resource that cause its ref count to get bumped aren't accounted for here.
1338 */
1339 if (graceful_unload_possible(mod, dependents)) {
1340 int i, res = 0;
1341 size_t num_deps = AST_VECTOR_SIZE(dependents);
1342 ast_debug(1, "%lu module%s will need to be unloaded\n", AST_VECTOR_SIZE(dependents), ESS(AST_VECTOR_SIZE(dependents)));
1343 /* Unload from the end, since the last module was the first one added, which means it isn't a dependency of anything else. */
1344 for (i = AST_VECTOR_SIZE(dependents) - 1; i >= 0; i--) {
1345 const char *depname = AST_VECTOR_GET(dependents, i);
1346 res = ast_unload_resource(depname, force);
1347 if (res) {
1348 ast_log(LOG_WARNING, "Failed to unload %lu module%s automatically (%s could not be unloaded)\n", num_deps, ESS(num_deps), depname);
1349 /* To be polite, load modules that we already unloaded,
1350 * to try to leave things the way they were when we started. */
1351 for (i++; i < num_deps; i++) {
1352 const char *depname = AST_VECTOR_GET(dependents, i);
1353 res = ast_load_resource(depname);
1354 if (res) {
1355 ast_log(LOG_WARNING, "Could not load module '%s' again automatically\n", depname);
1356 }
1357 }
1358 break;
1359 }
1360 }
1361 /* Either we failed, or we successfully unloaded everything.
1362 * If we succeeded, we can now proceed and unload ourselves. */
1363 }
1364 }
1365
1366 if (!error && (mod->usecount > 0)) {
1367 if (force) {
1368 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", resource_name, mod->usecount);
1369 } else {
1370 ast_log(LOG_WARNING, "%s unload failed, '%s' has use count %d\n", recursive ? "Recursive soft" : "Soft", resource_name, mod->usecount);
1371 error = 1;
1372 }
1373 }
1374
1375 if (!error) {
1376 /* Request any channels attached to the module to hangup. */
1378
1379 ast_verb(4, "Unloading %s\n", mod->resource);
1380 res = mod->info->unload();
1381 if (res) {
1382 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
1383 if (force <= AST_FORCE_FIRM) {
1384 error = 1;
1385 } else {
1386 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
1387 }
1388 }
1389
1390 if (!error) {
1391 /*
1392 * Request hangup on any channels that managed to get attached
1393 * while we called the module unload function.
1394 */
1396 sched_yield();
1397 }
1398 }
1399
1400 if (!error)
1401 mod->flags.running = mod->flags.declined = 0;
1402
1403exit:
1405
1406 if (!error) {
1408 ast_test_suite_event_notify("MODULE_UNLOAD", "Message: %s", resource_name);
1410 publish_unload_message(resource_name, "Success");
1411 }
1412
1413 return res;
1414}
#define ESS(x)
Definition: cli.h:59
static void publish_unload_message(const char *name, const char *status)
Definition: loader.c:1712
void __ast_module_user_hangup_all(struct ast_module *mod)
Definition: loader.c:862
static void unload_dynamic_module(struct ast_module *mod)
Definition: loader.c:1009
static int graceful_unload_possible(struct ast_module *target, struct ast_vector_const_string *dependents)
Whether or not this module should be able to be unloaded successfully, if we recursively unload any m...
Definition: loader.c:1234
@ AST_FORCE_FIRM
Definition: module.h:63
int(* unload)(void)
Definition: module.h:362
int error(const char *format,...)
Definition: utils/frame.c:999

References __ast_module_user_hangup_all(), ast_debug, AST_DLLIST_LOCK, AST_DLLIST_UNLOCK, AST_FORCE_FIRM, ast_load_resource(), ast_log, ast_test_suite_event_notify, ast_unload_resource(), ast_update_use_count(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_verb, ast_module::declined, error(), ESS, find_resource(), ast_module::flags, graceful_unload_possible(), ast_module::info, LOG_NOTICE, LOG_WARNING, publish_unload_message(), ast_module::resource, ast_module::running, ast_module_info::unload, unload_dynamic_module(), and ast_module::usecount.

Referenced by ast_refresh_resource(), and ast_unload_resource().

◆ find_resource()

static struct ast_module * find_resource ( const char *  resource,
int  do_lock 
)
static

◆ get_name_from_resource()

static char * get_name_from_resource ( const char *  resource)
static

Definition at line 166 of file loader.c.

167{
168 int len;
169 const char *last_three;
170 char *mod_name;
171
172 if (!resource) {
173 return NULL;
174 }
175
176 len = strlen(resource);
177 if (len > 3) {
178 last_three = &resource[len-3];
179 if (!strcasecmp(last_three, ".so")) {
180 mod_name = ast_calloc(1, len - 2);
181 if (mod_name) {
182 ast_copy_string(mod_name, resource, len - 2);
183 return mod_name;
184 } else {
185 /* Unable to allocate memory. */
186 return NULL;
187 }
188 }
189 }
190
191 /* Resource is the name - happens when manually unloading a module. */
192 mod_name = ast_calloc(1, len + 1);
193 if (mod_name) {
194 ast_copy_string(mod_name, resource, len + 1);
195 return mod_name;
196 }
197
198 /* Unable to allocate memory. */
199 return NULL;
200}
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425

References ast_calloc, ast_copy_string(), len(), and NULL.

Referenced by load_modules().

◆ graceful_unload_possible()

static int graceful_unload_possible ( struct ast_module target,
struct ast_vector_const_string dependents 
)
static

Whether or not this module should be able to be unloaded successfully, if we recursively unload any modules that are dependent on it.

Note
module_list should be locked when calling this
Return values
0if not, 1 if likely possible

Definition at line 1234 of file loader.c.

1235{
1236 struct ast_module *mod;
1237 int usecount = target->usecount;
1238
1239 /* Check the reffed_deps of each module to see if we're one of them. */
1242 const char *name;
1243 /* This module is dependent on the target.
1244 * If we can unload this module gracefully,
1245 * then that would decrement our use count.
1246 * If any single module could not be unloaded gracefully,
1247 * then we don't proceed. */
1248 int unloadable;
1249 if (AST_VECTOR_GET_CMP(dependents, ast_module_name(mod), !strcasecmp)) {
1250 /* Already in our list, we already checked this module,
1251 * and we gave it the green light. */
1252 ast_debug(3, "Skipping duplicate dependent %s\n", ast_module_name(mod));
1253 if (!--usecount) {
1254 break;
1255 }
1256 continue;
1257 }
1258 unloadable = graceful_unload_possible(mod, dependents);
1259 if (!unloadable) {
1260 ast_log(LOG_NOTICE, "Can't unload %s right now because %s is dependent on it\n", ast_module_name(target), ast_module_name(mod));
1261 return 0;
1262 }
1263 /* Insert at beginning, so later if we're loading modules again automatically, we can do so in the same order. */
1265 if (!name) {
1266 return 0;
1267 }
1268 ast_debug(3, "Found new dependent %s\n", ast_module_name(mod));
1269 if (AST_VECTOR_INSERT_AT(dependents, 0, name)) {
1270 ast_log(LOG_ERROR, "Failed to add module '%s' to vector\n", ast_module_name(mod));
1271 return 0;
1272 }
1273 if (!--usecount) {
1274 break;
1275 }
1276 }
1277 }
1278
1279 if (usecount) {
1280 ast_log(LOG_NOTICE, "Module %s cannot be unloaded (would still have use count %d/%d after unloading dependents)\n", ast_module_name(target), usecount, target->usecount);
1281 return 0;
1282 }
1283 return 1;
1284}
#define LOG_ERROR
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:624
#define AST_VECTOR_INSERT_AT(vec, idx, elem)
Insert an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:338
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition: vector.h:731
#define AST_VECTOR_ELEM_DEFAULT_CMP(elem, value)
Default comparator for AST_VECTOR_REMOVE_ELEM_UNORDERED()
Definition: vector.h:564

References ast_debug, AST_DLLIST_TRAVERSE, ast_log, ast_module_name(), ast_strdup, AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_GET_CMP, AST_VECTOR_INSERT_AT, ast_module::entry, graceful_unload_possible(), LOG_ERROR, LOG_NOTICE, name, ast_module::reffed_deps, and ast_module::usecount.

Referenced by auto_unload_resource(), and graceful_unload_possible().

◆ inspect_module()

static unsigned int inspect_module ( const struct ast_module mod)
static

Definition at line 1819 of file loader.c.

1820{
1821 if (!mod->info->description) {
1822 module_load_error("Module '%s' does not provide a description.\n", mod->resource);
1823 return 1;
1824 }
1825
1826 if (!mod->info->key) {
1827 module_load_error("Module '%s' does not provide a license key.\n", mod->resource);
1828 return 1;
1829 }
1830
1831 if (verify_key((unsigned char *) mod->info->key)) {
1832 module_load_error("Module '%s' did not provide a valid license key.\n", mod->resource);
1833 return 1;
1834 }
1835
1836 if (!ast_strlen_zero(mod->info->buildopt_sum) &&
1837 strcmp(buildopt_sum, mod->info->buildopt_sum)) {
1838 module_load_error("Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
1839 module_load_error("Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
1840 return 1;
1841 }
1842
1843 return 0;
1844}
static char buildopt_sum[33]
Definition: loader.c:147
static void module_load_error(const char *fmt,...)
Definition: loader.c:278
static int verify_key(const unsigned char *key)
Definition: loader.c:899
const char buildopt_sum[33]
Definition: module.h:377
const char * key
Definition: module.h:373

References ast_strlen_zero(), ast_module_info::buildopt_sum, buildopt_sum, ast_module_info::description, ast_module::info, ast_module_info::key, module_load_error(), ast_module::resource, and verify_key().

Referenced by load_resource().

◆ is_module_loaded()

static int is_module_loaded ( const char *  resource_name)
static

Check to see if the given resource is loaded.

Parameters
resource_nameName of the resource, including .so suffix.
Returns
False (0) if module is not loaded.
True (non-zero) if module is loaded.

Definition at line 990 of file loader.c.

991{
992 char fn[PATH_MAX] = "";
993 void *lib;
994
995 snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR,
996 resource_name);
997
998 lib = dlopen(fn, RTLD_LAZY | RTLD_NOLOAD);
999
1000 if (lib) {
1001 logged_dlclose(resource_name, lib);
1002 return 1;
1003 }
1004
1005 return 0;
1006}
#define PATH_MAX
Definition: asterisk.h:40
static void logged_dlclose(const char *name, void *lib)
dlclose(), with failure logging.
Definition: loader.c:961
const char * ast_config_AST_MODULE_DIR
Definition: options.c:153

References ast_config_AST_MODULE_DIR, ast_module::lib, logged_dlclose(), and PATH_MAX.

Referenced by unload_dynamic_module().

◆ load_dlopen()

static struct ast_module * load_dlopen ( const char *  resource_in,
const char *  so_ext,
const char *  filename,
int  flags,
unsigned int  suppress_logging 
)
static

Definition at line 1069 of file loader.c.

1071{
1072 struct ast_module *mod;
1073
1075
1076 mod = ast_calloc(1, sizeof(*mod) + strlen(resource_in) + strlen(so_ext) + 1);
1077 if (!mod) {
1078 return NULL;
1079 }
1080
1081 sprintf(mod->resource, "%s%s", resource_in, so_ext); /* safe */
1082
1084 mod->lib = dlopen(filename, flags);
1085#if defined(HAVE_PERMANENT_DLOPEN)
1086 manual_mod_reg(mod->lib, mod->resource);
1087#endif
1089 struct ast_str *list;
1090 int c = 0;
1091 const char *dlerror_msg = ast_strdupa(S_OR(dlerror(), ""));
1092
1094 if (mod->lib) {
1095 module_load_error("Module '%s' did not register itself during load\n", resource_in);
1096 logged_dlclose(resource_in, mod->lib);
1097
1098 goto error_return;
1099 }
1100
1101 if (suppress_logging) {
1102 goto error_return;
1103 }
1104
1106 mod->lib = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
1107#if defined(HAVE_PERMANENT_DLOPEN)
1108 manual_mod_reg(mod->lib, mod->resource);
1109#endif
1112
1113 module_load_error("Error loading module '%s': %s\n", resource_in, dlerror_msg);
1114 logged_dlclose(resource_in, mod->lib);
1115
1116 goto error_return;
1117 }
1118
1119 list = ast_str_create(64);
1120 if (list) {
1121 if (module_post_register(mod)) {
1122 goto loaded_error;
1123 }
1124
1125 c = load_dlopen_missing(&list, &mod->requires);
1126 c += load_dlopen_missing(&list, &mod->enhances);
1127#ifndef OPTIONAL_API
1128 c += load_dlopen_missing(&list, &mod->optional_modules);
1129#endif
1130 }
1131
1132 if (list && ast_str_strlen(list)) {
1133 module_load_error("Error loading module '%s', missing %s: %s\n",
1134 resource_in, c == 1 ? "dependency" : "dependencies", ast_str_buffer(list));
1135 } else {
1136 module_load_error("Error loading module '%s': %s\n", resource_in, dlerror_msg);
1137 }
1138
1139loaded_error:
1140 ast_free(list);
1142
1143 return NULL;
1144
1145error_return:
1146 ast_free(mod);
1147
1148 return NULL;
1149 }
1150
1151 return mod;
1152}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define RTLD_LOCAL
Definition: loader.c:133
static int module_post_register(struct ast_module *mod)
Definition: loader.c:741
static int load_dlopen_missing(struct ast_str **list, struct ast_vector_string *deps)
Definition: loader.c:1039
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
void * lib
Definition: loader.c:307
Support for dynamic strings.
Definition: strings.h:623
static struct test_val c
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_calloc, ast_free, ast_str_buffer(), ast_str_create, ast_str_strlen(), ast_strdupa, c, ast_module::enhances, ast_module::flags, ast_module::lib, load_dlopen_missing(), logged_dlclose(), module_load_error(), module_post_register(), NULL, ast_module::optional_modules, ast_module::requires, ast_module::resource, resource_being_loaded, RTLD_LOCAL, S_OR, and unload_dynamic_module().

Referenced by load_dynamic_module().

◆ load_dlopen_missing()

static int load_dlopen_missing ( struct ast_str **  list,
struct ast_vector_string deps 
)
static

Definition at line 1039 of file loader.c.

1040{
1041 int i;
1042 int c = 0;
1043
1044 for (i = 0; i < AST_VECTOR_SIZE(deps); i++) {
1045 const char *dep = AST_VECTOR_GET(deps, i);
1046 if (!find_resource(dep, 0)) {
1047 STR_APPEND_TEXT(dep, list);
1048 c++;
1049 }
1050 }
1051
1052 return c;
1053}
#define STR_APPEND_TEXT(txt, str)
Definition: loader.c:153

References AST_VECTOR_GET, AST_VECTOR_SIZE, c, find_resource(), and STR_APPEND_TEXT.

Referenced by load_dlopen().

◆ load_dynamic_module()

static struct ast_module * load_dynamic_module ( const char *  resource_in,
unsigned int  suppress_logging 
)
static

Definition at line 1154 of file loader.c.

1155{
1156 char fn[PATH_MAX];
1157 struct ast_module *mod;
1158 size_t resource_in_len = strlen(resource_in);
1159 const char *so_ext = "";
1160
1161 if (resource_in_len < 4 || strcasecmp(resource_in + resource_in_len - 3, ".so")) {
1162 so_ext = ".so";
1163 }
1164
1165 snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, so_ext);
1166
1167 /* Try loading in quiet mode first with RTLD_LOCAL. The majority of modules do not
1168 * export symbols so this allows the least number of calls to dlopen. */
1169 mod = load_dlopen(resource_in, so_ext, fn, RTLD_NOW | RTLD_LOCAL, suppress_logging);
1170
1171 if (!mod || !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
1172 return mod;
1173 }
1174
1175 /* Close the module so we can reopen with correct flags. */
1176 logged_dlclose(resource_in, mod->lib);
1177
1178 return load_dlopen(resource_in, so_ext, fn, RTLD_NOW | RTLD_GLOBAL, 0);
1179}
#define RTLD_NOW
Definition: loader.c:129
static struct ast_module * load_dlopen(const char *resource_in, const char *so_ext, const char *filename, int flags, unsigned int suppress_logging)
Definition: loader.c:1069
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:330

References ast_config_AST_MODULE_DIR, AST_MODFLAG_GLOBAL_SYMBOLS, ast_test_flag, ast_module::info, ast_module::lib, load_dlopen(), logged_dlclose(), PATH_MAX, RTLD_LOCAL, and RTLD_NOW.

Referenced by load_resource().

◆ load_modules()

int load_modules ( void  )

Provided by loader.c

Definition at line 2517 of file loader.c.

2518{
2519 struct load_order_entry *order;
2520 unsigned int load_count;
2521 struct load_order load_order;
2522 int res = 0;
2523 int modulecount = 0;
2524 int i;
2525 struct ast_module *cur;
2526#ifdef AST_XML_DOCS
2527 struct ast_str *warning_msg;
2528 char deprecated_in[33];
2529 char removed_in[33];
2530 char replacement[129];
2531#endif
2532 struct timeval start_time = ast_tvnow();
2533 struct timeval end_time;
2534 int64_t usElapsed;
2535
2536 ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
2537
2538#if defined(HAVE_PERMANENT_DLOPEN)
2540 info_list_obj_cmp_fn); /* must not be cleaned at shutdown */
2541 if (!info_list) {
2542 fprintf(stderr, "Module info list allocation failure.\n");
2543 return 1;
2544 }
2545#endif
2546
2549
2552
2554 if (res) {
2555 goto done;
2556 }
2557
2559 if (res) {
2560 goto done;
2561 }
2562
2563 load_count = 0;
2565 load_count++;
2566
2567 if (load_count)
2568 ast_log(LOG_NOTICE, "%u modules will be loaded.\n", load_count);
2569
2570 res = load_resource_list(&load_order, &modulecount);
2571 if (res == -1) {
2572 ast_log(LOG_WARNING, "Some non-required modules failed to load.\n");
2573 res = 0;
2574 }
2575
2576done:
2577 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
2578 ast_free(order->resource);
2579 ast_free(order);
2580 }
2581
2582#ifdef AST_XML_DOCS
2583 warning_msg = ast_str_create(512);
2584#endif
2585
2586 AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
2587#ifdef AST_XML_DOCS
2588 char *mod_name = NULL;
2589 struct ast_xml_xpath_results *results;
2590#endif
2591
2592 if (!cur->flags.running || cur->flags.declined) {
2593 continue;
2594 }
2595
2596#ifdef AST_XML_DOCS
2597 mod_name = get_name_from_resource(cur->resource);
2598 if (!warning_msg || !mod_name) {
2599 /* If we can't allocate memory, we have bigger issues */
2600 ast_free(mod_name);
2601 continue;
2602 }
2603
2604 /* Clear out the previous values */
2605 deprecated_in[0] = removed_in[0] = replacement[0] = 0;
2606
2607 results = ast_xmldoc_query("/docs/module[@name='%s']", mod_name);
2608 if (results) {
2609 struct ast_xml_node *deprecated_node, *removed_node, *replacement_node;
2610 struct ast_xml_node *metadata_nodes = ast_xml_node_get_children(ast_xml_xpath_get_first_result(results));
2611
2612 deprecated_node = ast_xml_find_element(metadata_nodes, "deprecated_in", NULL, NULL);
2613 if (deprecated_node) {
2614 const char *result_tmp = ast_xml_get_text(deprecated_node);
2615 if (!ast_strlen_zero(result_tmp)) {
2616 ast_copy_string(deprecated_in, result_tmp, sizeof(deprecated_in));
2617 }
2618 }
2619
2620 removed_node = ast_xml_find_element(metadata_nodes, "removed_in", NULL, NULL);
2621 if (removed_node) {
2622 const char *result_tmp = ast_xml_get_text(removed_node);
2623 if (!ast_strlen_zero(result_tmp)) {
2624 ast_copy_string(removed_in, result_tmp, sizeof(removed_in));
2625 }
2626 }
2627
2628 replacement_node = ast_xml_find_element(metadata_nodes, "replacement", NULL, NULL);
2629 if (replacement_node) {
2630 const char *result_tmp = ast_xml_get_text(replacement_node);
2631 if (!ast_strlen_zero(result_tmp)) {
2632 ast_copy_string(replacement, result_tmp, sizeof(replacement));
2633 }
2634 }
2635
2637 }
2638
2639 ast_str_reset(warning_msg);
2640
2641 if (cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED || !ast_strlen_zero(deprecated_in)
2642 || !ast_strlen_zero(removed_in) || !ast_strlen_zero(replacement)) {
2643 int already_butted = 0;
2644
2645 ast_str_append(&warning_msg, -1, "Module '%s' has been loaded", mod_name);
2646 if (!ast_strlen_zero(deprecated_in)) {
2647 ast_str_append(&warning_msg, -1, " but %s deprecated in Asterisk version %s",
2648 cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED ? "was" : "will be", deprecated_in);
2649 already_butted = 1;
2650 }
2651
2652 if (!ast_strlen_zero(removed_in)) {
2653 ast_str_append(&warning_msg, -1, " %s will be removed in Asterisk version %s", already_butted ? "and" : "but", removed_in);
2654 } else {
2655 ast_str_append(&warning_msg, -1, " %s may be removed in a future release", already_butted ? "and" : "but");
2656 }
2657
2658 ast_str_append(&warning_msg, -1, ".");
2659
2660 if (!ast_strlen_zero(replacement)) {
2661 ast_str_append(&warning_msg, -1, " Its replacement is '%s'.", replacement);
2662 }
2663 }
2664
2665 if (ast_str_strlen(warning_msg)) {
2666 ast_log(LOG_WARNING, "%s\n", ast_str_buffer(warning_msg));
2667 }
2668
2669 ast_free(mod_name);
2670#else
2672 ast_log(LOG_WARNING, "The deprecated module '%s' has been loaded and is running, it may be removed in a future version\n", cur->resource);
2673 }
2674#endif
2675 }
2676
2677#ifdef AST_XML_DOCS
2678 ast_free(warning_msg);
2679#endif
2680
2682
2683
2684 for (i = 0; i < AST_VECTOR_SIZE(&startup_errors); i++) {
2685 char *str = AST_VECTOR_GET(&startup_errors, i);
2686
2687 ast_log(LOG_ERROR, "%s", str);
2688 ast_free(str);
2689 }
2691
2694
2695 end_time = ast_tvnow();
2696 usElapsed = ast_tvdiff_us(end_time, start_time);
2697
2698#ifdef AST_XML_DOCS
2699 ast_debug(1, "Loader time with AST_XML_DOCS: %" PRId64 ".%06" PRId64 "\n", usElapsed / 1000000, usElapsed % 1000000);
2700#else
2701 ast_debug(1, "Loader time without AST_XML_DOCS: %" PRId64 ".%06" PRId64 "\n", usElapsed / 1000000, usElapsed % 1000000);
2702#endif
2703
2704 return res;
2705}
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
static int load_resource_list(struct load_order *load_order, int *mod_count)
Definition: loader.c:2280
static struct ast_vector_string startup_errors
Definition: loader.c:162
static struct ast_str * startup_error_builder
Definition: loader.c:163
static int loader_config_init(struct load_order *load_order)
Definition: loader.c:2393
static int loader_builtin_init(struct load_order *load_order)
Definition: loader.c:2358
static char * get_name_from_resource(const char *resource)
Definition: loader.c:166
@ AST_MODULE_SUPPORT_DEPRECATED
Definition: module.h:123
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
int done
Definition: test_amihooks.c:48
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:87
struct ast_xml_node * ast_xml_node_get_children(struct ast_xml_node *node)
Get the node's children.
Definition: xml.c:395
const char * ast_xml_get_text(struct ast_xml_node *node)
Get an element content string.
Definition: xml.c:353
struct ast_xml_node * ast_xml_xpath_get_first_result(struct ast_xml_xpath_results *results)
Return the first result node of an XPath query.
Definition: xml.c:415
void ast_xml_xpath_results_free(struct ast_xml_xpath_results *results)
Free the XPath results.
Definition: xml.c:425
struct ast_xml_node * ast_xml_find_element(struct ast_xml_node *root_node, const char *name, const char *attrname, const char *attrvalue)
Find a node element by name.
Definition: xml.c:297
struct ast_xml_xpath_results * ast_xmldoc_query(const char *fmt,...)
Execute an XPath query on the loaded XML documentation.
Definition: xmldoc.c:2670

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_list, ast_copy_string(), ast_debug, AST_DLLIST_LOCK, AST_DLLIST_TRAVERSE, AST_DLLIST_UNLOCK, ast_free, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, ast_log, AST_MODULE_SUPPORT_DEPRECATED, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_reset(), ast_str_strlen(), ast_strlen_zero(), ast_tvdiff_us(), ast_tvnow(), AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_SIZE, ast_verb, ast_xml_find_element(), ast_xml_get_text(), ast_xml_node_get_children(), ast_xml_xpath_get_first_result(), ast_xml_xpath_results_free(), ast_xmldoc_query(), ast_module::declined, done, ast_module::flags, get_name_from_resource(), ast_module::info, load_resource_list(), loader_builtin_init(), loader_config_init(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, NULL, order, ast_module::resource, ast_module::running, startup_error_builder, startup_errors, str, and ast_module_info::support_level.

Referenced by asterisk_daemon().

◆ load_resource()

static enum ast_module_load_result load_resource ( const char *  resource_name,
unsigned int  suppress_logging,
struct module_vector module_priorities,
int  required,
int  preload 
)
static

loads a resource based upon resource_name. If global_symbols_only is set only modules with global symbols will be loaded.

If the module_vector is provided (not NULL) the module is found and added to the vector without running the module's load() function. By doing this, modules can be initialized later in order by priority and dependencies.

If the module_vector is not provided, the module's load function will be executed immediately

Definition at line 1931 of file loader.c.

1933{
1934 struct ast_module *mod;
1936
1937 if ((mod = find_resource(resource_name, 0))) {
1938 if (mod->flags.running) {
1939 ast_log(LOG_WARNING, "Module '%s' already loaded and running.\n", resource_name);
1941 }
1942 } else {
1943 mod = load_dynamic_module(resource_name, suppress_logging);
1944 if (!mod) {
1946 }
1947
1948 if (module_post_register(mod)) {
1949 goto prestart_error;
1950 }
1951 }
1952
1953 mod->flags.required |= required;
1954 mod->flags.preload |= preload;
1955
1956 if (inspect_module(mod)) {
1957 goto prestart_error;
1958 }
1959
1960 mod->flags.declined = 0;
1961
1962 if (module_priorities) {
1963 if (AST_VECTOR_ADD_SORTED(module_priorities, mod, module_vector_cmp)) {
1964 goto prestart_error;
1965 }
1967 } else {
1968 res = start_resource(mod);
1969 }
1970
1972 publish_load_message(resource_name, res);
1973 }
1974
1975 return res;
1976
1977prestart_error:
1978 module_load_error("Module '%s' could not be loaded.\n", resource_name);
1982 publish_load_message(resource_name, res);
1983 }
1984 return res;
1985}
int ast_shutdown_final(void)
Definition: asterisk.c:1878
static struct ast_module * load_dynamic_module(const char *resource_in, unsigned int suppress_logging)
Definition: loader.c:1154
static int module_vector_cmp(struct ast_module *a, struct ast_module *b)
Definition: loader.c:380
static unsigned int inspect_module(const struct ast_module *mod)
Definition: loader.c:1819
static enum ast_module_load_result start_resource(struct ast_module *mod)
Definition: loader.c:1846
static void publish_load_message(const char *name, enum ast_module_load_result result)
Definition: loader.c:1699
@ AST_MODULE_LOAD_PRIORITY
Definition: module.h:90
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition: module.h:102
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_fully_booted
Definition: options.h:117
unsigned int required
Definition: loader.c:337
unsigned int preload
Definition: loader.c:339

References ast_fully_booted, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SUCCESS, ast_shutdown_final(), AST_VECTOR_ADD_SORTED, ast_module::declined, find_resource(), ast_module::flags, inspect_module(), load_dynamic_module(), LOG_WARNING, module_load_error(), module_post_register(), module_vector_cmp(), ast_module::preload, publish_load_message(), ast_module::required, ast_module::running, start_resource(), and unload_dynamic_module().

Referenced by ast_load_resource(), and load_resource_list().

◆ load_resource_list()

static int load_resource_list ( struct load_order load_order,
int *  mod_count 
)
static

loads modules in order by load_pri, updates mod_count

Returns
-1 on failure to load module, -2 on failure to load required module, otherwise 0

Definition at line 2280 of file loader.c.

2281{
2282 struct module_vector module_priorities;
2283 struct load_order_entry *order;
2284 int attempt = 0;
2285 int count = 0;
2286 int res = 0;
2287 int didwork;
2288 int lasttry = 0;
2289
2290 if (AST_VECTOR_INIT(&module_priorities, 500)) {
2291 ast_log(LOG_ERROR, "Failed to initialize module loader.\n");
2292
2293 return -1;
2294 }
2295
2296 while (res != -2) {
2297 didwork = 0;
2298
2300 enum ast_module_load_result lres;
2301
2302 /* Suppress log messages unless this is the last pass */
2303 lres = load_resource(order->resource, !lasttry, &module_priorities, order->required, order->preload);
2304 ast_debug(3, "PASS %d: %-46s %d\n", attempt, order->resource, lres);
2305 switch (lres) {
2308 /* We're supplying module_priorities so SUCCESS isn't possible but we
2309 * still have to test for it. SKIP is only used when we try to start a
2310 * module that is missing dependencies. */
2311 break;
2313 res = -1;
2314 break;
2316 /* LOAD_FAILURE only happens for required modules */
2317 if (lasttry) {
2318 /* This run is just to print errors. */
2319 module_load_error("*** Failed to load module %s - Required\n", order->resource);
2320 fprintf(stderr, "*** Failed to load module %s - Required\n", order->resource);
2321 res = -2;
2322 }
2323 break;
2325 /* load_resource worked and the module was added to module_priorities */
2327 ast_free(order->resource);
2328 ast_free(order);
2329 didwork = 1;
2330 break;
2331 }
2332 }
2334
2335 if (!didwork) {
2336 if (lasttry) {
2337 break;
2338 }
2339 /* We know the next try is going to fail, it's only being performed
2340 * so we can print errors. */
2341 lasttry = 1;
2342 }
2343 attempt++;
2344 }
2345
2346 if (res != -2) {
2347 res = start_resource_list(&module_priorities, &count);
2348 }
2349
2350 if (mod_count) {
2351 *mod_count += count;
2352 }
2353 AST_VECTOR_FREE(&module_priorities);
2354
2355 return res;
2356}
static int start_resource_list(struct module_vector *resources, int *mod_count)
Definition: loader.c:2148
@ AST_MODULE_LOAD_SKIP
Definition: module.h:84

References ast_debug, ast_free, 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_VECTOR_FREE, AST_VECTOR_INIT, load_order_entry::entry, load_resource(), LOG_ERROR, module_load_error(), order, and start_resource_list().

Referenced by load_modules().

◆ loader_builtin_init()

static int loader_builtin_init ( struct load_order load_order)
static

Definition at line 2358 of file loader.c.

2359{
2360 struct ast_module *mod;
2361
2362 /*
2363 * All built-in modules have registered the first time, now it's time to complete
2364 * the registration and add them to the priority list.
2365 */
2366 loader_ready = 1;
2367
2369 /* ast_module_register doesn't finish when first run by built-in modules. */
2371 }
2372
2373 /* Add all built-in modules to the load order. */
2375 if (!mod->flags.builtin) {
2376 continue;
2377 }
2378
2379 /* Parse dependencies from mod->info. */
2380 if (module_post_register(mod)) {
2381 return -1;
2382 }
2383
2384 /* Built-in modules are not preloaded, most have an early load priority. */
2385 if (!add_to_load_order(mod->resource, load_order, 0, 0, 1)) {
2386 return -1;
2387 }
2388 }
2389
2390 return 0;
2391}
#define AST_DLLIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
static struct load_order_entry * add_to_load_order(const char *resource, struct load_order *load_order, int required, int preload, int builtin)
Definition: loader.c:2021
void ast_module_register(const struct ast_module_info *info)
Definition: loader.c:668

References add_to_load_order(), AST_DLLIST_REMOVE_HEAD, AST_DLLIST_TRAVERSE, ast_module_register(), ast_module::builtin, builtin_module_list, ast_module::entry, ast_module::flags, ast_module::info, loader_ready, module_post_register(), ast_module::resource, and resource_being_loaded.

Referenced by load_modules().

◆ loader_config_init()

static int loader_config_init ( struct load_order load_order)
static

Definition at line 2393 of file loader.c.

2394{
2395 int res = -1;
2396 struct load_order_entry *order;
2397 struct ast_config *cfg;
2398 struct ast_variable *v;
2399 struct ast_flags config_flags = { 0 };
2400
2401 cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
2403 ast_log(LOG_WARNING, "'%s' invalid or missing.\n", AST_MODULE_CONFIG);
2404
2405 return -1;
2406 }
2407
2408 /* first, find all the modules we have been explicitly requested to load */
2409 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
2410 int required;
2411 int preload = 0;
2412
2413 if (!strncasecmp(v->name, "preload", strlen("preload"))) {
2414 preload = 1;
2415 if (!strcasecmp(v->name, "preload")) {
2416 required = 0;
2417 } else if (!strcasecmp(v->name, "preload-require")) {
2418 required = 1;
2419 } else {
2420 ast_log(LOG_ERROR, "Unknown configuration option '%s'", v->name);
2421 goto done;
2422 }
2423 } else if (!strcasecmp(v->name, "load")) {
2424 required = 0;
2425 } else if (!strcasecmp(v->name, "require")) {
2426 required = 1;
2427 } else if (!strcasecmp(v->name, "noload") || !strcasecmp(v->name, "autoload")) {
2428 continue;
2429 } else {
2430 ast_log(LOG_ERROR, "Unknown configuration option '%s'", v->name);
2431 goto done;
2432 }
2433
2434 if (required) {
2435 ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
2436 }
2437
2438 if (!add_to_load_order(v->value, load_order, required, preload, 0)) {
2439 goto done;
2440 }
2441 }
2442
2443 /* check if 'autoload' is on */
2444 if (ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
2445 /* if we are allowed to load dynamic modules, scan the directory for
2446 for all available modules and add them as well */
2447 DIR *dir = opendir(ast_config_AST_MODULE_DIR);
2448 struct dirent *dirent;
2449
2450 if (dir) {
2451 while ((dirent = readdir(dir))) {
2452 int ld = strlen(dirent->d_name);
2453
2454 /* Must end in .so to load it. */
2455
2456 if (ld < 4)
2457 continue;
2458
2459 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
2460 continue;
2461
2462 /* if there is already a module by this name in the module_list,
2463 skip this file */
2464 if (find_resource(dirent->d_name, 0))
2465 continue;
2466
2467 if (!add_to_load_order(dirent->d_name, load_order, 0, 0, 0)) {
2468 closedir(dir);
2469 goto done;
2470 }
2471 }
2472
2473 closedir(dir);
2474 } else {
2475 ast_log(LOG_ERROR, "Unable to open modules directory '%s'.\n", ast_config_AST_MODULE_DIR);
2476 goto done;
2477 }
2478 }
2479
2480 /* now scan the config for any modules we are prohibited from loading and
2481 remove them from the load order */
2482 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
2483 size_t baselen;
2484
2485 if (strcasecmp(v->name, "noload")) {
2486 continue;
2487 }
2488
2489 baselen = resource_name_baselen(v->value);
2491 if (!resource_name_match(v->value, baselen, order->resource)) {
2492 if (order->builtin) {
2493 ast_log(LOG_ERROR, "%s is a built-in module, you cannot specify 'noload'.\n", v->value);
2494 goto done;
2495 }
2496
2497 if (order->required) {
2498 ast_log(LOG_ERROR, "%s is configured with '%s' and 'noload', this is impossible.\n",
2499 v->value, order->preload ? "preload-require" : "require");
2500 goto done;
2501 }
2503 ast_free(order->resource);
2504 ast_free(order);
2505 }
2506 }
2508 }
2509
2510 res = 0;
2511done:
2512 ast_config_destroy(cfg);
2513
2514 return res;
2515}
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3541
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:869
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#define AST_MODULE_CONFIG
Module configuration file.
Definition: module.h:59
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
Structure used to handle boolean flags.
Definition: utils.h:199
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

References add_to_load_order(), ast_config_AST_MODULE_DIR, ast_config_destroy(), ast_config_load2(), ast_debug, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, AST_MODULE_CONFIG, ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, done, find_resource(), LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, order, resource_name_baselen(), resource_name_match(), and ast_variable::value.

Referenced by load_modules().

◆ loadresult2str()

static const char * loadresult2str ( enum ast_module_load_result  result)
static

Definition at line 1682 of file loader.c.

1683{
1684 int i;
1685 for (i = 0; i < ARRAY_LEN(load_results); i++) {
1686 if (load_results[i].result == result) {
1687 return load_results[i].name;
1688 }
1689 }
1690
1691 ast_log(LOG_WARNING, "Failed to find correct load result status. result %d\n", result);
1693}
static PGresult * result
Definition: cel_pgsql.c:84
static const struct load_results_map load_results[]
Definition: loader.c:353
#define AST_MODULE_LOAD_UNKNOWN_STRING
Definition: loader.c:360
const char * name
Definition: loader.c:350
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_log, AST_MODULE_LOAD_UNKNOWN_STRING, load_results, LOG_WARNING, load_results_map::name, and result.

Referenced by publish_load_message().

◆ logged_dlclose()

static void logged_dlclose ( const char *  name,
void *  lib 
)
static

dlclose(), with failure logging.

Definition at line 961 of file loader.c.

962{
963 char *error;
964
965 if (!lib) {
966 return;
967 }
968
969 /* Clear any existing error */
970 dlerror();
971 if (dlclose(lib)) {
972 error = dlerror();
973 ast_log(AST_LOG_ERROR, "Failure in dlclose for module '%s': %s\n",
974 S_OR(name, "unknown"), S_OR(error, "Unknown error"));
975#if defined(HAVE_PERMANENT_DLOPEN)
976 } else {
977 manual_mod_unreg(name);
978#endif
979 }
980}
#define AST_LOG_ERROR

References ast_log, AST_LOG_ERROR, error(), ast_module::lib, name, and S_OR.

Referenced by is_module_loaded(), load_dlopen(), load_dynamic_module(), and unload_dynamic_module().

◆ module_deps_missing_recursive()

static int module_deps_missing_recursive ( struct ast_module mod,
struct module_vector missingdeps 
)
static

Recursively find required dependencies that are not running.

Parameters
modModule to scan for dependencies.
missingdepsVector listing modules that must be started first.
Return values
0All dependencies resolved.
-1Failed to resolve some dependencies.

An error from this function usually means a required module is not even loaded. This function is safe from infinite recursion, but dependency loops are not reported as an error from here. On success missingdeps will contain a list of every module that needs to be running before this module can start. missingdeps is sorted by load priority so any missing dependencies can be started if needed.

Definition at line 575 of file loader.c.

576{
577 int i = 0;
578 int res = -1;
579 struct ast_vector_const_string localdeps;
580 struct ast_module *dep;
581
582 /*
583 * localdeps stores a copy of all dependencies that mod could not reference.
584 * First we discard modules that we've already found. We add all newly found
585 * modules to the missingdeps vector then scan them recursively. This will
586 * ensure we quickly run out of stuff to do.
587 */
588 AST_VECTOR_INIT(&localdeps, 0);
589 if (module_deps_reference(mod, &localdeps)) {
590 goto clean_return;
591 }
592
593 while (i < AST_VECTOR_SIZE(&localdeps)) {
594 dep = find_resource(AST_VECTOR_GET(&localdeps, i), 0);
595 if (!dep) {
596 goto clean_return;
597 }
598
599 if (AST_VECTOR_GET_CMP(missingdeps, dep, AST_VECTOR_ELEM_DEFAULT_CMP)) {
600 /* Skip common dependency. We have already searched it. */
601 AST_VECTOR_REMOVE(&localdeps, i, 0);
602 } else {
603 /* missingdeps is the real list so keep it sorted. */
604 if (AST_VECTOR_ADD_SORTED(missingdeps, dep, module_vector_cmp)) {
605 goto clean_return;
606 }
607 i++;
608 }
609 }
610
611 res = 0;
612 for (i = 0; !res && i < AST_VECTOR_SIZE(&localdeps); i++) {
613 dep = find_resource(AST_VECTOR_GET(&localdeps, i), 0);
614 /* We've already confirmed dep is loaded in the first loop. */
615 res = module_deps_missing_recursive(dep, missingdeps);
616 }
617
618clean_return:
619 AST_VECTOR_FREE(&localdeps);
620
621 return res;
622}
static int module_deps_reference(struct ast_module *mod, struct ast_vector_const_string *missing)
Definition: loader.c:543
static int module_deps_missing_recursive(struct ast_module *mod, struct module_vector *missingdeps)
Recursively find required dependencies that are not running.
Definition: loader.c:575
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412

References AST_VECTOR_ADD_SORTED, AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_GET_CMP, AST_VECTOR_INIT, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, find_resource(), module_deps_missing_recursive(), module_deps_reference(), and module_vector_cmp().

Referenced by module_deps_missing_recursive(), resource_list_recursive_decline(), start_resource(), and start_resource_list().

◆ module_deps_process_reqlist()

static int module_deps_process_reqlist ( struct ast_module mod,
struct ast_vector_string vec,
struct ast_vector_const_string missing,
int  ref_enhancers,
int  isoptional 
)
static

Definition at line 494 of file loader.c.

497{
498 int idx;
499
500 for (idx = 0; idx < AST_VECTOR_SIZE(vec); idx++) {
501 const char *depname = AST_VECTOR_GET(vec, idx);
502 struct ast_module *dep = find_resource(depname, 0);
503
504 if (!dep || !dep->flags.running) {
505 if (isoptional && !dep) {
506 continue;
507 }
508
509 if (missing && !AST_VECTOR_APPEND(missing, depname)) {
510 continue;
511 }
512
513 return -1;
514 }
515
516 if (module_reffed_deps_add(mod, dep, missing)) {
517 return -1;
518 }
519
520 if (ref_enhancers && module_reffed_deps_add_dep_enhancers(mod, dep, missing)) {
521 return -1;
522 }
523 }
524
525 return 0;
526}
static int module_reffed_deps_add(struct ast_module *mod, struct ast_module *dep, struct ast_vector_const_string *missing)
Definition: loader.c:425
static int module_reffed_deps_add_dep_enhancers(struct ast_module *mod, struct ast_module *dep, struct ast_vector_const_string *missing)
Definition: loader.c:457
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References AST_VECTOR_APPEND, AST_VECTOR_GET, AST_VECTOR_SIZE, find_resource(), ast_module::flags, module_reffed_deps_add(), module_reffed_deps_add_dep_enhancers(), and ast_module::running.

Referenced by module_deps_reference().

◆ module_deps_reference()

static int module_deps_reference ( struct ast_module mod,
struct ast_vector_const_string missing 
)
static

Definition at line 543 of file loader.c.

544{
545 int res = 0;
546
547 /* Grab references to modules we enhance but not other enhancements. */
548 res |= module_deps_process_reqlist(mod, &mod->enhances, missing, 0, 0);
549
550 /* Grab references to modules we require plus enhancements. */
551 res |= module_deps_process_reqlist(mod, &mod->requires, missing, 1, 0);
552
553 /* Grab references to optional modules including enhancements. */
554 res |= module_deps_process_reqlist(mod, &mod->optional_modules, missing, 1, 1);
555
556 return res;
557}
static int module_deps_process_reqlist(struct ast_module *mod, struct ast_vector_string *vec, struct ast_vector_const_string *missing, int ref_enhancers, int isoptional)
Definition: loader.c:494

References ast_module::enhances, module_deps_process_reqlist(), ast_module::optional_modules, and ast_module::requires.

Referenced by module_deps_missing_recursive(), start_resource(), start_resource_attempt(), and start_resource_list().

◆ module_destroy()

static void module_destroy ( struct ast_module mod)
static

Definition at line 753 of file loader.c.

754{
757
760
763
764 /* Release references to all dependencies. */
767
770 if (mod->flags.builtin) {
771 ast_std_free(mod);
772 } else {
773 ast_free(mod);
774 }
775}
void ast_std_free(void *ptr)
Definition: astmm.c:1734
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:653
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:862

References ao2_cleanup, ast_free, AST_LIST_HEAD_DESTROY, ast_module_unref, ast_std_free(), AST_VECTOR_CALLBACK_VOID, AST_VECTOR_FREE, ast_module::builtin, ast_module::enhances, ast_module::flags, ast_module::optional_modules, ast_module::ref_debug, ast_module::reffed_deps, ast_module::requires, and ast_module::users.

Referenced by ast_module_unregister(), and modules_shutdown().

◆ module_load_error()

static void module_load_error ( const char *  fmt,
  ... 
)
static

Definition at line 278 of file loader.c.

279{
280 char *copy = NULL;
281 va_list ap;
282
283 va_start(ap, fmt);
289 ast_free(copy);
290 }
291 } else {
292 ast_log_ap(LOG_ERROR, fmt, ap);
293 }
294 va_end(ap);
295}
static int copy(char *infile, char *outfile)
Utility function to copy a file.
void ast_log_ap(int level, const char *file, int line, const char *function, const char *fmt, va_list ap)
Definition: logger.c:2437
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
Definition: strings.h:1030

References ast_free, ast_log, ast_log_ap(), ast_str_buffer(), ast_str_set_va(), ast_strdup, AST_VECTOR_APPEND, copy(), LOG_ERROR, NULL, startup_error_builder, and startup_errors.

Referenced by inspect_module(), load_dlopen(), load_resource(), load_resource_list(), resource_list_recursive_decline(), start_resource(), start_resource_attempt(), and start_resource_list().

◆ module_load_helper()

static void module_load_helper ( const char *  word)
static

Definition at line 1524 of file loader.c.

1525{
1526 struct module_load_word word_l = {
1527 .word = word,
1528 .len = strlen(word),
1529 .moddir_len = strlen(ast_config_AST_MODULE_DIR),
1530 };
1531
1535}
int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth)
Recursively iterate through files and directories up to max_depth.
Definition: file.c:1282
static int module_load_helper_on_file(const char *dir_name, const char *filename, void *obj)
Definition: loader.c:1492
const char * word
Definition: loader.c:1487

References ast_config_AST_MODULE_DIR, AST_DLLIST_LOCK, AST_DLLIST_UNLOCK, ast_file_read_dirs(), module_load_helper_on_file(), and module_load_word::word.

Referenced by ast_module_helper().

◆ module_load_helper_on_file()

static int module_load_helper_on_file ( const char *  dir_name,
const char *  filename,
void *  obj 
)
static

Definition at line 1492 of file loader.c.

1493{
1494 struct module_load_word *word = obj;
1495 struct ast_module *mod;
1496 char *filename_merged = NULL;
1497
1498 /* dir_name will never be shorter than word->moddir_len. */
1499 dir_name += word->moddir_len;
1500 if (!ast_strlen_zero(dir_name)) {
1501 ast_assert(dir_name[0] == '/');
1502
1503 dir_name += 1;
1504 if (ast_asprintf(&filename_merged, "%s/%s", dir_name, filename) < 0) {
1505 /* If we can't allocate the string just give up! */
1506 return -1;
1507 }
1508 filename = filename_merged;
1509 }
1510
1511 if (!strncasecmp(filename, word->word, word->len)) {
1512 /* Don't list files that are already loaded! */
1513 mod = find_resource(filename, 0);
1514 if (!mod || !mod->flags.running) {
1516 }
1517 }
1518
1519 ast_free(filename_merged);
1520
1521 return 0;
1522}
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2768

References ast_asprintf, ast_assert, ast_cli_completion_add(), ast_free, ast_strdup, ast_strlen_zero(), find_resource(), ast_module::flags, NULL, and ast_module::running.

Referenced by module_load_helper().

◆ module_matches_helper_type()

static int module_matches_helper_type ( struct ast_module mod,
enum ast_module_helper_type  type 
)
static

Definition at line 1462 of file loader.c.

1463{
1464 switch (type) {
1466 return !mod->usecount && mod->flags.running && !mod->flags.declined;
1467
1469 return mod->flags.running && mod->info->reload;
1470
1472 return mod->flags.running;
1473
1475 /* if we have a 'struct ast_module' then we're loaded. */
1476 return 1;
1477 default:
1478 /* This function is not called for AST_MODULE_HELPER_LOAD. */
1479 /* Unknown ast_module_helper_type. Assume it doesn't match. */
1480 ast_assert(0);
1481
1482 return 0;
1483 }
1484}
@ AST_MODULE_HELPER_RELOAD
Definition: module.h:131
@ AST_MODULE_HELPER_LOADED
Definition: module.h:129
@ AST_MODULE_HELPER_UNLOAD
Definition: module.h:135
@ AST_MODULE_HELPER_RUNNING
Definition: module.h:137
int(* reload)(void)
Definition: module.h:360

References ast_assert, AST_MODULE_HELPER_LOADED, AST_MODULE_HELPER_RELOAD, AST_MODULE_HELPER_RUNNING, AST_MODULE_HELPER_UNLOAD, ast_module::declined, ast_module::flags, ast_module::info, ast_module_info::reload, ast_module::running, type, and ast_module::usecount.

Referenced by ast_module_helper().

◆ module_post_register()

static int module_post_register ( struct ast_module mod)
static

Definition at line 741 of file loader.c.

742{
743 int res;
744
745 /* Split lists from mod->info. */
746 res = ast_vector_string_split(&mod->requires, mod->info->requires, ",", 0, strcasecmp);
747 res |= ast_vector_string_split(&mod->optional_modules, mod->info->optional_modules, ",", 0, strcasecmp);
748 res |= ast_vector_string_split(&mod->enhances, mod->info->enhances, ",", 0, strcasecmp);
749
750 return res;
751}
const char *const char * optional_modules
Comma-separated list of optionally required modules.
Definition: module.h:397
const char * enhances
Modules that we provide enhanced functionality for.
Definition: module.h:420
int ast_vector_string_split(struct ast_vector_string *dest, const char *input, const char *delim, int flags, int(*excludes_cmp)(const char *s1, const char *s2))
Append a string vector by splitting a string.
Definition: strings.c:406

References ast_vector_string_split(), ast_module_info::enhances, ast_module::enhances, ast_module::info, ast_module_info::optional_modules, ast_module::optional_modules, and ast_module::requires.

Referenced by load_dlopen(), load_resource(), and loader_builtin_init().

◆ module_reffed_deps_add()

static int module_reffed_deps_add ( struct ast_module mod,
struct ast_module dep,
struct ast_vector_const_string missing 
)
static

Definition at line 425 of file loader.c.

427{
428 if (!dep->flags.running) {
429 return !missing ? -1 : AST_VECTOR_APPEND(missing, dep->info->name);
430 }
431
433 /* Skip duplicate. */
434 return 0;
435 }
436
437 if (AST_VECTOR_APPEND(&mod->reffed_deps, dep)) {
438 return -1;
439 }
440
441 ast_module_ref(dep);
442
443 return 0;
444}
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:457

References ast_module_ref, AST_VECTOR_APPEND, AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_GET_CMP, ast_module::flags, ast_module::info, ast_module_info::name, ast_module::reffed_deps, and ast_module::running.

Referenced by module_deps_process_reqlist(), and module_reffed_deps_add_dep_enhancers().

◆ module_reffed_deps_add_dep_enhancers()

static int module_reffed_deps_add_dep_enhancers ( struct ast_module mod,
struct ast_module dep,
struct ast_vector_const_string missing 
)
static

Definition at line 457 of file loader.c.

459{
460 struct ast_module *cur;
461
463 if (cur->flags.declined) {
464 continue;
465 }
466
467 if (!AST_VECTOR_GET_CMP(&cur->enhances, dep->info->name, !strcasecmp)) {
468 /* dep is not enhanced by cur. */
469 continue;
470 }
471
472 /* dep is enhanced by cur, therefore mod requires cur. */
473 if (module_reffed_deps_add(mod, cur, missing)) {
474 return -1;
475 }
476 }
477
478 return 0;
479}

References AST_DLLIST_TRAVERSE, AST_VECTOR_GET_CMP, ast_module::declined, ast_module::enhances, ast_module::entry, ast_module::flags, ast_module::info, module_reffed_deps_add(), and ast_module_info::name.

Referenced by module_deps_process_reqlist().

◆ module_vector_cmp()

static int module_vector_cmp ( struct ast_module a,
struct ast_module b 
)
static

Definition at line 380 of file loader.c.

381{
382 int preload_diff = (int)b->flags.preload - (int)a->flags.preload;
383 /* if load_pri is not set, default is 128. Lower is better */
384 int a_pri = ast_test_flag(a->info, AST_MODFLAG_LOAD_ORDER)
385 ? a->info->load_pri : AST_MODPRI_DEFAULT;
386 int b_pri = ast_test_flag(b->info, AST_MODFLAG_LOAD_ORDER)
387 ? b->info->load_pri : AST_MODPRI_DEFAULT;
388
389 if (preload_diff) {
390 /* -1 preload a but not b */
391 /* 0 preload both or neither */
392 /* 1 preload b but not a */
393 return preload_diff;
394 }
395
396 /*
397 * Returns comparison values for a vector sorted by priority.
398 * <0 a_pri < b_pri
399 * =0 a_pri == b_pri
400 * >0 a_pri > b_pri
401 */
402 return a_pri - b_pri;
403}
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
@ AST_MODPRI_DEFAULT
Definition: module.h:346
static struct test_val b
static struct test_val a

References a, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_DEFAULT, ast_test_flag, and b.

Referenced by load_resource(), and module_deps_missing_recursive().

◆ module_vector_strcasecmp()

static int module_vector_strcasecmp ( struct ast_module a,
struct ast_module b 
)
static

Definition at line 375 of file loader.c.

376{
377 return strcasecmp(a->resource, b->resource);
378}

References a, and b.

Referenced by alpha_module_list_create().

◆ modules_shutdown()

int modules_shutdown ( void  )

Provided by loader.c

Note
Some resources, like timers, are started up dynamically, and thus may be still in use, even if all channels are dead. We must therefore check the usecount before asking modules to unload.

Definition at line 1181 of file loader.c.

1182{
1183 struct ast_module *mod;
1184 int somethingchanged;
1185 int res;
1186
1188
1189 /*!\note Some resources, like timers, are started up dynamically, and thus
1190 * may be still in use, even if all channels are dead. We must therefore
1191 * check the usecount before asking modules to unload. */
1192 do {
1193 /* Reset flag before traversing the list */
1194 somethingchanged = 0;
1195
1197 if (mod->usecount) {
1198 ast_debug(1, "Passing on %s: its use count is %d\n",
1199 mod->resource, mod->usecount);
1200 continue;
1201 }
1203 if (mod->flags.running && !mod->flags.declined && mod->info->unload) {
1204 ast_verb(4, "Unloading %s\n", mod->resource);
1205 mod->info->unload();
1206 }
1207 module_destroy(mod);
1208 somethingchanged = 1;
1209 }
1211 if (!somethingchanged) {
1213 if (mod->flags.keepuntilshutdown) {
1214 ast_module_unref(mod);
1215 mod->flags.keepuntilshutdown = 0;
1216 somethingchanged = 1;
1217 }
1218 }
1219 }
1220 } while (somethingchanged);
1221
1224
1225 return !res;
1226}
#define AST_DLLIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: dlinkedlists.h:469

References ast_debug, AST_DLLIST_EMPTY, AST_DLLIST_LOCK, AST_DLLIST_REMOVE_CURRENT, AST_DLLIST_TRAVERSE, AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN, AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END, AST_DLLIST_UNLOCK, ast_module_unref, ast_verb, ast_module::declined, ast_module::entry, ast_module::flags, ast_module::info, ast_module::keepuntilshutdown, module_destroy(), ast_module::resource, ast_module::running, ast_module_info::unload, and ast_module::usecount.

Referenced by really_quit().

◆ printdigest()

static int printdigest ( const unsigned char *  d)
static

Definition at line 884 of file loader.c.

885{
886 int x, pos;
887 char buf[256]; /* large enough so we don't have to worry */
888
889 for (pos = 0, x = 0; x < 16; x++)
890 pos += sprintf(buf + pos, " %02hhx", *d++);
891
892 ast_debug(1, "Unexpected signature:%s\n", buf);
893
894 return 0;
895}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct test_val d

References ast_debug, buf, and d.

Referenced by verify_key().

◆ publish_load_message()

static void publish_load_message ( const char *  name,
enum ast_module_load_result  result 
)
static

Definition at line 1699 of file loader.c.

1700{
1701 const char *status;
1702
1704
1706}
jack_status_t status
Definition: app_jack.c:149
static void publish_load_message_type(const char *type, const char *name, const char *status)
Definition: loader.c:1643
static const char * loadresult2str(enum ast_module_load_result result)
Definition: loader.c:1682

References loadresult2str(), name, publish_load_message_type(), result, and status.

Referenced by load_resource().

◆ publish_load_message_type()

static void publish_load_message_type ( const char *  type,
const char *  name,
const char *  status 
)
static
Since
12

Definition at line 1643 of file loader.c.

1644{
1646 RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
1647 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1648 RAII_VAR(struct ast_json *, event_object, NULL, ast_json_unref);
1649
1650 ast_assert(type != NULL);
1653
1655 return;
1656 }
1657
1658 event_object = ast_json_pack("{s:s, s:s}",
1659 "Module", name,
1660 "Status", status);
1661 json_object = ast_json_pack("{s:s, s:i, s:o}",
1662 "type", type,
1663 "class_type", EVENT_FLAG_SYSTEM,
1664 "event", ast_json_ref(event_object));
1665 if (!json_object) {
1666 return;
1667 }
1668
1669 payload = ast_json_payload_create(json_object);
1670 if (!payload) {
1671 return;
1672 }
1673
1675 if (!message) {
1676 return;
1677 }
1678
1680}
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:454
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json_payload * ast_json_payload_create(struct ast_json *json)
Create an ao2 object to pass json blobs as data payloads for stasis.
Definition: json.c:756
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
struct stasis_message_type * ast_manager_get_generic_type(void)
Get the stasis_message_type for generic messages.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1538
Abstract JSON element (object, array, string, int, ...).
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ast_assert, ast_json_pack(), ast_json_payload_create(), ast_json_ref(), ast_json_unref(), ast_manager_get_generic_type(), ast_manager_get_topic(), ast_strlen_zero(), EVENT_FLAG_SYSTEM, name, NULL, RAII_VAR, stasis_message_create(), stasis_publish(), status, and type.

Referenced by publish_load_message(), publish_reload_message(), and publish_unload_message().

◆ publish_reload_message()

static void publish_reload_message ( const char *  name,
enum ast_module_reload_result  result 
)
static
Since
12

Definition at line 1722 of file loader.c.

1723{
1724 char res_buffer[8];
1725
1726 snprintf(res_buffer, sizeof(res_buffer), "%u", result);
1727 publish_load_message_type("Reload", S_OR(name, "All"), res_buffer);
1728}

References name, publish_load_message_type(), result, and S_OR.

Referenced by ast_module_reload().

◆ publish_unload_message()

static void publish_unload_message ( const char *  name,
const char *  status 
)
static

Definition at line 1712 of file loader.c.

1713{
1715}

References name, publish_load_message_type(), and status.

Referenced by auto_unload_resource().

◆ queue_reload_request()

static void queue_reload_request ( const char *  module)
static

Definition at line 1600 of file loader.c.

1601{
1602 struct reload_queue_item *item;
1603
1605
1606 if (do_full_reload) {
1608 return;
1609 }
1610
1611 if (ast_strlen_zero(module)) {
1612 /* A full reload request (when module is NULL) wipes out any previous
1613 reload requests and causes the queue to ignore future ones */
1615 ast_free(item);
1616 }
1617 do_full_reload = 1;
1618 } else {
1619 /* No reason to add the same module twice */
1621 if (!strcasecmp(item->module, module)) {
1623 return;
1624 }
1625 }
1626 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
1627 if (!item) {
1628 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
1630 return;
1631 }
1632 strcpy(item->module, module);
1634 }
1636}
char module[0]
Definition: loader.c:644

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, reload_queue_item::entry, item, LOG_ERROR, and reload_queue_item::module.

Referenced by ast_module_reload().

◆ resource_list_recursive_decline()

static int resource_list_recursive_decline ( struct module_vector resources,
struct ast_module mod,
struct ast_str **  printmissing 
)
static

Definition at line 2085 of file loader.c.

2087{
2088 struct module_vector missingdeps;
2089 struct ast_vector_const_string localdeps;
2090 int i = 0;
2091 int res = -1;
2092
2093 mod->flags.declined = 1;
2094 if (mod->flags.required) {
2095 module_load_error("Required module %s declined to load.\n", ast_module_name(mod));
2096
2097 return -2;
2098 }
2099
2100 module_load_error("%s declined to load.\n", ast_module_name(mod));
2101
2102 if (!*printmissing) {
2103 *printmissing = ast_str_create(64);
2104 if (!*printmissing) {
2105 return -1;
2106 }
2107 } else {
2108 ast_str_reset(*printmissing);
2109 }
2110
2111 AST_VECTOR_INIT(&missingdeps, 0);
2112 AST_VECTOR_INIT(&localdeps, 0);
2113
2114 /* Decline everything that depends on 'mod' from resources so we can
2115 * print a concise list. */
2116 while (res != -2 && i < AST_VECTOR_SIZE(resources)) {
2117 struct ast_module *dep = AST_VECTOR_GET(resources, i);
2118 i++;
2119
2121 if (dep->flags.declined || module_deps_missing_recursive(dep, &missingdeps)) {
2122 continue;
2123 }
2124
2125 if (AST_VECTOR_GET_CMP(&missingdeps, mod, AST_VECTOR_ELEM_DEFAULT_CMP)) {
2126 dep->flags.declined = 1;
2127 if (dep->flags.required) {
2128 module_load_error("Cannot load required module %s that depends on %s\n",
2129 ast_module_name(dep), ast_module_name(mod));
2130 res = -2;
2131 } else {
2132 AST_VECTOR_APPEND(&localdeps, ast_module_name(dep));
2133 }
2134 }
2135 }
2136 AST_VECTOR_FREE(&missingdeps);
2137
2138 if (res != -2 && AST_VECTOR_SIZE(&localdeps)) {
2139 AST_VECTOR_CALLBACK_VOID(&localdeps, STR_APPEND_TEXT, printmissing);
2140 module_load_error("Declined modules which depend on %s: %s\n",
2141 ast_module_name(mod), ast_str_buffer(*printmissing));
2142 }
2143 AST_VECTOR_FREE(&localdeps);
2144
2145 return res;
2146}
A vector of strings commonly used throughout this module.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:571

References ast_module_name(), ast_str_buffer(), ast_str_create, ast_str_reset(), AST_VECTOR_APPEND, AST_VECTOR_CALLBACK_VOID, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_GET_CMP, AST_VECTOR_INIT, AST_VECTOR_RESET, AST_VECTOR_SIZE, ast_module::declined, ast_module::flags, module_deps_missing_recursive(), module_load_error(), ast_module::required, and STR_APPEND_TEXT.

Referenced by start_resource_list().

◆ resource_name_baselen()

static size_t resource_name_baselen ( const char *  name)
static

Definition at line 916 of file loader.c.

917{
918 size_t len = strlen(name);
919
920 if (len > 3 && !strcasecmp(name + len - 3, ".so")) {
921 return len - 3;
922 }
923
924 return len;
925}

References len(), and name.

Referenced by add_to_load_order(), ast_module_reload(), find_resource(), loader_config_init(), and resource_name_match().

◆ resource_name_match()

static int resource_name_match ( const char *  name1,
size_t  baselen1,
const char *  name2 
)
static

Definition at line 927 of file loader.c.

928{
929 if (baselen1 != resource_name_baselen(name2)) {
930 return -1;
931 }
932
933 return strncasecmp(name1, name2, baselen1);
934}

References resource_name_baselen().

Referenced by add_to_load_order(), ast_module_reload(), find_resource(), and loader_config_init().

◆ start_resource()

static enum ast_module_load_result start_resource ( struct ast_module mod)
static

Definition at line 1846 of file loader.c.

1847{
1848 char tmp[256];
1849 enum ast_module_load_result res;
1850
1851 if (mod->flags.running) {
1853 }
1854
1855 if (!mod->info->load) {
1856 mod->flags.declined = 1;
1857
1859 }
1860
1861 if (module_deps_reference(mod, NULL)) {
1862 struct module_vector missing;
1863 int i;
1864
1865 AST_VECTOR_INIT(&missing, 0);
1866 if (module_deps_missing_recursive(mod, &missing)) {
1867 module_load_error("%s has one or more unknown dependencies.\n", mod->info->name);
1868 }
1869 for (i = 0; i < AST_VECTOR_SIZE(&missing); i++) {
1870 module_load_error("%s loaded before dependency %s!\n", mod->info->name,
1871 AST_VECTOR_GET(&missing, i)->info->name);
1872 }
1873 AST_VECTOR_FREE(&missing);
1874
1876 }
1877
1878 if (!ast_fully_booted) {
1879 ast_verb(4, "Loading %s.\n", mod->resource);
1880 }
1881 res = mod->info->load();
1882
1883 switch (res) {
1885 if (!ast_fully_booted) {
1886 ast_verb(5, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
1887 } else {
1888 ast_verb(4, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
1889 }
1890
1891 mod->flags.running = 1;
1892 if (mod->flags.builtin) {
1893 /* Built-in modules cannot be unloaded. */
1895 }
1896
1898 break;
1900 mod->flags.declined = 1;
1901 if (mod->flags.required) {
1903 }
1904 break;
1906 mod->flags.declined = 1;
1907 break;
1908 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
1910 break;
1911 }
1912
1913 /* Make sure the newly started module is at the end of the list */
1915 AST_DLLIST_REMOVE(&module_list, mod, entry);
1916 AST_DLLIST_INSERT_TAIL(&module_list, mod, entry);
1918
1919 return res;
1920}
#define AST_DLLIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:478
enum ast_module_load_result(* load)(void)
Definition: module.h:358
#define COLOR_BROWN
Definition: term.h:56
#define COLOR_BLACK
Definition: term.h:50
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:235

References AST_DLLIST_INSERT_TAIL, AST_DLLIST_LOCK, AST_DLLIST_REMOVE, AST_DLLIST_UNLOCK, ast_fully_booted, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_module_shutdown_ref, ast_update_use_count(), AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_SIZE, ast_verb, ast_module::builtin, COLOR_BLACK, COLOR_BROWN, ast_module::declined, ast_module_info::description, ast_module::flags, sip_to_pjsip::info(), ast_module::info, ast_module_info::load, module_deps_missing_recursive(), module_deps_reference(), module_load_error(), ast_module_info::name, NULL, ast_module::required, ast_module::resource, ast_module::running, and term_color().

Referenced by load_resource(), and start_resource_attempt().

◆ start_resource_attempt()

static enum ast_module_load_result start_resource_attempt ( struct ast_module mod,
int *  count 
)
static

Definition at line 2057 of file loader.c.

2058{
2059 enum ast_module_load_result lres;
2060
2061 /* Try to grab required references. */
2062 if (module_deps_reference(mod, NULL)) {
2063 /* We're likely to retry so not an error. */
2064 ast_debug(1, "Module %s is missing dependencies\n", mod->resource);
2065 return AST_MODULE_LOAD_SKIP;
2066 }
2067
2068 lres = start_resource(mod);
2069 ast_debug(3, "START: %-46s[%d] %d\n",
2070 mod->resource,
2072 lres);
2073
2074 if (lres == AST_MODULE_LOAD_SUCCESS) {
2075 (*count)++;
2076 } else if (lres == AST_MODULE_LOAD_FAILURE) {
2077 module_load_error("*** Failed to load %smodule %s\n",
2078 mod->flags.required ? "required " : "",
2079 mod->resource);
2080 }
2081
2082 return lres;
2083}
unsigned char load_pri
Definition: module.h:384

References ast_debug, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_DEFAULT, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_test_flag, ast_module::flags, ast_module::info, ast_module_info::load_pri, module_deps_reference(), module_load_error(), NULL, ast_module::required, ast_module::resource, and start_resource().

Referenced by start_resource_list().

◆ start_resource_list()

static int start_resource_list ( struct module_vector resources,
int *  mod_count 
)
static

Definition at line 2148 of file loader.c.

2149{
2150 struct module_vector missingdeps;
2151 int res = 0;
2152 struct ast_str *printmissing = NULL;
2153
2154 AST_VECTOR_INIT(&missingdeps, 0);
2155 while (res != -2 && AST_VECTOR_SIZE(resources)) {
2156 struct ast_module *mod = AST_VECTOR_REMOVE(resources, 0, 1);
2157 enum ast_module_load_result lres;
2158
2159 if (mod->flags.declined) {
2160 ast_debug(1, "%s is already declined, skipping\n", ast_module_name(mod));
2161 continue;
2162 }
2163
2164retry_load:
2165 lres = start_resource_attempt(mod, mod_count);
2166 if (lres == AST_MODULE_LOAD_SUCCESS) {
2167 /* No missing dependencies, successful. */
2168 continue;
2169 }
2170
2171 if (lres == AST_MODULE_LOAD_FAILURE) {
2172 res = -2;
2173 break;
2174 }
2175
2176 if (lres == AST_MODULE_LOAD_DECLINE) {
2177 res = resource_list_recursive_decline(resources, mod, &printmissing);
2178 continue;
2179 }
2180
2181 if (module_deps_missing_recursive(mod, &missingdeps)) {
2183 module_load_error("Failed to resolve dependencies for %s\n", ast_module_name(mod));
2184 res = resource_list_recursive_decline(resources, mod, &printmissing);
2185 continue;
2186 }
2187
2188 if (!AST_VECTOR_SIZE(&missingdeps)) {
2189 module_load_error("%s load function returned an invalid result. "
2190 "This is a bug in the module.\n", ast_module_name(mod));
2191 /* Dependencies were met but the module failed to start and the result
2192 * code was not AST_MODULE_LOAD_FAILURE or AST_MODULE_LOAD_DECLINE. */
2193 res = resource_list_recursive_decline(resources, mod, &printmissing);
2194 continue;
2195 }
2196
2197 ast_debug(1, "%s has %d dependencies\n",
2198 ast_module_name(mod), (int)AST_VECTOR_SIZE(&missingdeps));
2199 while (AST_VECTOR_SIZE(&missingdeps)) {
2200 int didwork = 0;
2201 int i = 0;
2202
2203 while (i < AST_VECTOR_SIZE(&missingdeps)) {
2204 struct ast_module *dep = AST_VECTOR_GET(&missingdeps, i);
2205
2206 if (dep->flags.declined) {
2207 ast_debug(1, "%s tried to start %s but it's already declined\n",
2208 ast_module_name(mod), ast_module_name(dep));
2209 i++;
2210 continue;
2211 }
2212
2213 ast_debug(1, "%s trying to start %s\n", ast_module_name(mod), ast_module_name(dep));
2214 lres = start_resource_attempt(dep, mod_count);
2215 if (lres == AST_MODULE_LOAD_SUCCESS) {
2216 ast_debug(1, "%s started %s\n", ast_module_name(mod), ast_module_name(dep));
2217 AST_VECTOR_REMOVE(&missingdeps, i, 1);
2220 didwork++;
2221 continue;
2222 }
2223
2224 if (lres == AST_MODULE_LOAD_FAILURE) {
2225 module_load_error("Failed to load %s.\n", ast_module_name(dep));
2226 res = -2;
2227 goto exitpoint;
2228 }
2229
2230 ast_debug(1, "%s failed to start %s\n", ast_module_name(mod), ast_module_name(dep));
2231 i++;
2232 }
2233
2234 if (!didwork) {
2235 break;
2236 }
2237 }
2238
2239 if (AST_VECTOR_SIZE(&missingdeps)) {
2240 if (!printmissing) {
2241 printmissing = ast_str_create(64);
2242 } else {
2243 ast_str_reset(printmissing);
2244 }
2245
2246 if (printmissing) {
2247 struct ast_vector_const_string localdeps;
2248
2249 AST_VECTOR_INIT(&localdeps, 0);
2250 module_deps_reference(mod, &localdeps);
2251 AST_VECTOR_CALLBACK_VOID(&localdeps, STR_APPEND_TEXT, &printmissing);
2252 AST_VECTOR_FREE(&localdeps);
2253 }
2254
2255 module_load_error("Failed to load %s due to dependencies: %s.\n",
2256 ast_module_name(mod),
2257 printmissing ? ast_str_buffer(printmissing) : "allocation failure creating list");
2258 res = resource_list_recursive_decline(resources, mod, &printmissing);
2259
2261
2262 continue;
2263 }
2264
2265 /* If we're here it means that we started with missingdeps and they're all loaded
2266 * now. It's impossible to reach this point a second time for the same module. */
2267 goto retry_load;
2268 }
2269
2270exitpoint:
2271 ast_free(printmissing);
2272 AST_VECTOR_FREE(&missingdeps);
2273
2274 return res;
2275}
static int resource_list_recursive_decline(struct module_vector *resources, struct ast_module *mod, struct ast_str **printmissing)
Definition: loader.c:2085
static enum ast_module_load_result start_resource_attempt(struct ast_module *mod, int *count)
Definition: loader.c:2057
#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison while maintaining order.
Definition: vector.h:540

References ast_debug, ast_free, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_module_name(), ast_str_buffer(), ast_str_create, ast_str_reset(), AST_VECTOR_CALLBACK_VOID, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_REMOVE, AST_VECTOR_REMOVE_CMP_ORDERED, AST_VECTOR_RESET, AST_VECTOR_SIZE, ast_module::declined, ast_module::flags, module_deps_missing_recursive(), module_deps_reference(), module_load_error(), NULL, resource_list_recursive_decline(), start_resource_attempt(), and STR_APPEND_TEXT.

Referenced by load_resource_list().

◆ unload_dynamic_module()

static void unload_dynamic_module ( struct ast_module mod)
static

Definition at line 1009 of file loader.c.

1010{
1011#if defined(HAVE_RTLD_NOLOAD)
1012 char *name = ast_strdupa(ast_module_name(mod));
1013#endif
1014 void *lib = mod->lib;
1015
1016 /* WARNING: the structure pointed to by mod is going to
1017 disappear when this operation succeeds, so we can't
1018 dereference it */
1020
1021 /* There are several situations where the module might still be resident
1022 * in memory.
1023 *
1024 * If somehow there was another dlopen() on the same module (unlikely,
1025 * since that all is supposed to happen in loader.c).
1026 *
1027 * Avoid the temptation of repeating the dlclose(). The other code that
1028 * dlopened the module still has its module reference, and should close
1029 * it itself. In other situations, dlclose() will happily return success
1030 * for as many times as you wish to call it.
1031 */
1032#if defined(HAVE_RTLD_NOLOAD)
1033 if (is_module_loaded(name)) {
1034 ast_log(LOG_WARNING, "Module '%s' could not be completely unloaded\n", name);
1035 }
1036#endif
1037}
static int is_module_loaded(const char *resource_name)
Check to see if the given resource is loaded.
Definition: loader.c:990

References ast_log, ast_module_name(), ast_strdupa, is_module_loaded(), ast_module::lib, LOG_WARNING, logged_dlclose(), and name.

Referenced by auto_unload_resource(), load_dlopen(), and load_resource().

◆ verify_key()

static int verify_key ( const unsigned char *  key)
static

Definition at line 899 of file loader.c.

900{
901 struct MD5Context c;
902 unsigned char digest[16];
903
904 MD5Init(&c);
905 MD5Update(&c, key, strlen((char *)key));
906 MD5Final(digest, &c);
907
908 if (key_matches(expected_key, digest))
909 return 0;
910
911 printdigest(digest);
912
913 return -1;
914}
static const unsigned char expected_key[]
Definition: loader.c:143
static int printdigest(const unsigned char *d)
Definition: loader.c:884
#define key_matches(a, b)
Definition: loader.c:897
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
Definition: md5.c:72
void MD5Init(struct MD5Context *context)
Definition: md5.c:57
void MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], struct MD5Context *context)
Definition: md5.c:120
Definition: md5.h:30

References c, expected_key, key_matches, MD5Final(), MD5Init(), MD5Update(), and printdigest().

Referenced by inspect_module().

Variable Documentation

◆ buildopt_sum

char buildopt_sum[33] = AST_BUILDOPT_SUM
static

Definition at line 147 of file loader.c.

Referenced by inspect_module().

◆ builtin_module_list

struct module_list builtin_module_list
static

Definition at line 373 of file loader.c.

Referenced by ast_module_register(), and loader_builtin_init().

◆ do_full_reload

int do_full_reload = 0
static

Definition at line 647 of file loader.c.

Referenced by ast_process_pending_reloads(), and queue_reload_request().

◆ expected_key

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 143 of file loader.c.

Referenced by verify_key().

◆ load_results

const struct load_results_map load_results[]
static

Definition at line 353 of file loader.c.

Referenced by loadresult2str().

◆ loader_ready

unsigned int loader_ready
static

Definition at line 159 of file loader.c.

Referenced by ast_module_register(), and loader_builtin_init().

◆ module_list

struct module_list module_list = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ modules_loaded

int modules_loaded
static

Internal flag to indicate all modules have been initially loaded.

Definition at line 300 of file loader.c.

Referenced by ast_module_reload(), and ast_process_pending_reloads().

◆ reload_queue

struct reload_queue reload_queue = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ reloadlock

ast_mutex_t reloadlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 640 of file loader.c.

Referenced by ast_module_reload().

◆ resource_being_loaded

struct ast_module* volatile resource_being_loaded
static

Definition at line 659 of file loader.c.

Referenced by ast_module_register(), load_dlopen(), and loader_builtin_init().

◆ startup_error_builder

struct ast_str* startup_error_builder
static

Definition at line 163 of file loader.c.

Referenced by load_modules(), and module_load_error().

◆ startup_errors

struct ast_vector_string startup_errors
static

String container for deferring output of startup errors.

Definition at line 162 of file loader.c.

Referenced by load_modules(), and module_load_error().

◆ support_level_map

const char* support_level_map[]

Definition at line 2927 of file loader.c.

Referenced by ast_module_support_level_to_string().

◆ updaters

struct updaters updaters = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static