Asterisk - The Open Source Telephony Project GIT-master-5782b03
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 351 of file loader.c.

◆ key_matches

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

Definition at line 888 of file loader.c.

◆ RTLD_LOCAL

#define RTLD_LOCAL   0

Definition at line 124 of file loader.c.

◆ RTLD_NOW

#define RTLD_NOW   0

Definition at line 120 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:147
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 144 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 2868 of file loader.c.

2869{
2870 if (!mod) {
2871 return NULL;
2872 }
2873
2874 if (mod->ref_debug) {
2875 __ao2_ref(mod->ref_debug, +1, "", file, line, func);
2876 }
2877
2880
2881 return mod;
2882}
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:2698
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:757
#define NULL
Definition: resample.c:96
void * ref_debug
Definition: loader.c:296
int usecount
Definition: loader.c:300

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

2886{
2887 if (!mod || !mod->flags.running) {
2888 return NULL;
2889 }
2890
2891 return __ast_module_ref(mod, file, line, func);
2892}
struct ast_module * __ast_module_ref(struct ast_module *mod, const char *file, int line, const char *func)
Definition: loader.c:2868
unsigned int running
Definition: loader.c:320
struct ast_module::@362 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 2894 of file loader.c.

2895{
2896 if (!mod || mod->flags.keepuntilshutdown) {
2897 return;
2898 }
2899
2900 __ast_module_ref(mod, file, line, func);
2901 mod->flags.keepuntilshutdown = 1;
2902}
unsigned int keepuntilshutdown
Definition: loader.c:324

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

2905{
2906 if (!mod) {
2907 return;
2908 }
2909
2910 if (mod->ref_debug) {
2911 __ao2_ref(mod->ref_debug, -1, "", file, line, func);
2912 }
2913
2916}

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

801{
802 struct ast_module_user *u;
803
804 u = ast_calloc(1, sizeof(*u));
805 if (!u) {
806 return NULL;
807 }
808
809 u->chan = chan;
810
811 AST_LIST_LOCK(&mod->users);
813 AST_LIST_UNLOCK(&mod->users);
814
815 if (mod->ref_debug) {
816 ao2_ref(mod->ref_debug, +1);
817 }
818
820
822
823 return u;
824}
#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_channel * chan
Definition: loader.c:128
struct module_user_list users
Definition: loader.c:302
Definition: search.h:40

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

854{
855 struct ast_module_user *u;
856
857 AST_LIST_LOCK(&mod->users);
858 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
859 if (u->chan) {
861 }
862
863 if (mod->ref_debug) {
864 ao2_ref(mod->ref_debug, -1);
865 }
866
868 ast_free(u);
869 }
870 AST_LIST_UNLOCK(&mod->users);
871
873}
#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:2490
@ 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::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 826 of file loader.c.

827{
828 if (!u) {
829 return;
830 }
831
832 AST_LIST_LOCK(&mod->users);
833 u = AST_LIST_REMOVE(&mod->users, u, entry);
834 AST_LIST_UNLOCK(&mod->users);
835 if (!u) {
836 /*
837 * Was not in the list. Either a bad pointer or
838 * __ast_module_user_hangup_all() has been called.
839 */
840 return;
841 }
842
843 if (mod->ref_debug) {
844 ao2_ref(mod->ref_debug, -1);
845 }
846
848 ast_free(u);
849
851}
#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::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 2012 of file loader.c.

2013{
2014 struct load_order_entry *order;
2015 size_t resource_baselen = resource_name_baselen(resource);
2016
2018 if (!resource_name_match(resource, resource_baselen, order->resource)) {
2019 /* Make sure we have the proper setting for the required field
2020 (we might have both load= and required= lines in modules.conf) */
2021 order->required |= required;
2022 order->preload |= preload;
2023 return order;
2024 }
2025 }
2026
2027 order = ast_calloc(1, sizeof(*order));
2028 if (!order) {
2029 return NULL;
2030 }
2031
2032 order->resource = ast_strdup(resource);
2033 if (!order->resource) {
2034 ast_free(order);
2035
2036 return NULL;
2037 }
2038 order->required = required;
2039 order->preload = preload;
2040 order->builtin = builtin;
2042
2043 return order;
2044}
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:918
static size_t resource_name_baselen(const char *name)
Definition: loader.c:907
Definition: loader.c:2002
int builtin
Definition: loader.c:2006
int required
Definition: loader.c:2004
int preload
Definition: loader.c:2005
char * resource
Definition: loader.c:2003

References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, load_order_entry::builtin, 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 2720 of file loader.c.

2721{
2722 struct ast_module *cur;
2723
2724 if (AST_VECTOR_INIT(alpha_module_list, 32)) {
2725 return -1;
2726 }
2727
2729 if (AST_VECTOR_ADD_SORTED(alpha_module_list, cur, module_vector_strcasecmp)) {
2730 return -1;
2731 }
2732 }
2733
2734 return 0;
2735}
#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:366
#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, 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 1978 of file loader.c.

1979{
1980 struct ast_module *mod;
1981 enum ast_module_load_result res;
1982
1983 /* If we're trying to load a module that previously declined to load,
1984 * transparently unload it first so we dlclose, then dlopen it afresh.
1985 * Otherwise, we won't actually load a (potentially) updated module. */
1986 mod = find_resource(resource_name, 0);
1987 if (mod && mod->flags.declined) {
1988 ast_debug(1, "Module %s previously declined to load, unloading it first before loading again\n", resource_name);
1989 ast_unload_resource(resource_name, 0);
1990 }
1991
1993 res = load_resource(resource_name, 0, NULL, 0, 0);
1994 if (!res) {
1995 ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);
1996 }
1998
1999 return res;
2000}
#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:927
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:1922
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
Unload a module.
Definition: loader.c:1448
ast_module_load_result
Definition: module.h:68
unsigned int declined
Definition: loader.c:322
#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 2836 of file loader.c.

2837{
2838 struct loadupdate *tmp;
2839
2840 if (!(tmp = ast_malloc(sizeof(*tmp))))
2841 return -1;
2842
2843 tmp->updater = v;
2847
2848 return 0;
2849}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static int tmp()
Definition: bt_open.c:389

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

2852{
2853 struct loadupdate *cur;
2854
2857 if (cur->updater == v) {
2859 break;
2860 }
2861 }
2864
2865 return cur ? 0 : -1;
2866}
#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
int(* updater)(void)
Definition: loader.c:625

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

2824{
2825 struct ast_module *cur;
2826
2827 if (ast_strlen_zero(name))
2828 return 0; /* FALSE */
2829
2830 cur = find_resource(name, 1);
2831
2832 return (cur != NULL);
2833}
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 1528 of file loader.c.

1529{
1530 struct ast_module *mod;
1531 int which = 0;
1532 int wordlen = strlen(word);
1533 char *ret = NULL;
1534
1535 if (pos != rpos) {
1536 return NULL;
1537 }
1538
1539 /* Tab completion can't be used during startup, or CLI and loader will deadlock. */
1541 return NULL;
1542 }
1543
1546
1547 return NULL;
1548 }
1549
1552 if (!module_matches_helper_type(mod, type)) {
1553 continue;
1554 }
1555
1556 if (!strncasecmp(word, mod->resource, wordlen) && ++which > state) {
1557 ret = ast_strdup(mod->resource);
1558 break;
1559 }
1560 }
1562
1563 return ret;
1564}
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:1453
static void module_load_helper(const char *word)
Definition: loader.c:1515
@ AST_MODULE_HELPER_LOAD
Definition: module.h:133
char resource[0]
Definition: loader.c:333
#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, 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 615 of file loader.c.

616{
617 if (!mod || !mod->info) {
618 return NULL;
619 }
620
621 return mod->info->name;
622}
const char * name
Definition: module.h:364
const struct ast_module_info * info
Definition: loader.c:294

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

660{
661 struct ast_module *mod;
662
663 if (!loader_ready) {
664 mod = ast_std_calloc(1, sizeof(*mod) + strlen(info->name) + 1);
665 if (!mod) {
666 /* We haven't even reached main() yet, if we can't
667 * allocate memory at this point just give up. */
668 fprintf(stderr, "Allocation failure during startup.\n");
669 exit(2);
670 }
671 strcpy(mod->resource, info->name); /* safe */
672 mod->info = info;
673 mod->flags.builtin = 1;
675
676 /* ast_module_register for built-in modules is run again during module preload. */
677 return;
678 }
679
680 /*
681 * This lock protects resource_being_loaded as well as the module
682 * list. Normally we already have a lock on module_list when we
683 * begin the load but locking again from here prevents corruption
684 * if an asterisk module is dlopen'ed from outside the module loader.
685 */
688 if (!mod) {
690 return;
691 }
692
693 ast_debug(5, "Registering module %s\n", info->name);
694
695 /* This tells load_dynamic_module that we're registered. */
697
698 mod->info = info;
699 if (ast_opt_ref_debug) {
701 }
703 AST_VECTOR_INIT(&mod->requires, 0);
705 AST_VECTOR_INIT(&mod->enhances, 0);
707
710
711 /* give the module a copy of its own handle, for later use in registrations and the like */
712 *((struct ast_module **) &(info->self)) = mod;
713
714#if defined(HAVE_PERMANENT_DLOPEN)
715 if (mod->flags.builtin != 1) {
716 struct info_list_obj *obj_tmp = ao2_find(info_list, info->name,
718
719 if (!obj_tmp) {
720 obj_tmp = info_list_obj_alloc(info->name, info);
721 if (obj_tmp) {
722 ao2_link(info_list, obj_tmp);
723 ao2_ref(obj_tmp, -1);
724 }
725 } else {
726 ao2_ref(obj_tmp, -1);
727 }
728 }
729#endif
730}
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:150
static struct module_list builtin_module_list
Definition: loader.c:364
static struct ast_module *volatile resource_being_loaded
Definition: loader.c:650
def info(msg)
#define ast_opt_ref_debug
Definition: options.h:135
struct ast_vector_string requires
Definition: loader.c:305
struct ast_vector_string optional_modules
Definition: loader.c:307
struct module_vector reffed_deps
Vector holding pointers to modules we have a reference to.
Definition: loader.c:317
unsigned int builtin
Definition: loader.c:326
struct ast_vector_string enhances
Definition: loader.c:309

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

1722{
1723 struct ast_module *cur;
1725 size_t name_baselen = name ? resource_name_baselen(name) : 0;
1726
1727 /* If we aren't fully booted, we just pretend we reloaded but we queue this
1728 up to run once we are booted up. */
1729 if (!modules_loaded) {
1732 goto module_reload_exit;
1733 }
1734
1736 ast_verb(3, "The previous reload command didn't finish yet\n");
1738 goto module_reload_exit;
1739 }
1740 ast_sd_notify("RELOADING=1");
1742
1744 int try;
1745 int lockres;
1746 for (try = 1, lockres = AST_LOCK_TIMEOUT; try < 6 && (lockres == AST_LOCK_TIMEOUT); try++) {
1748 if (lockres == AST_LOCK_TIMEOUT) {
1749 ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try);
1750 }
1751 }
1752 if (lockres != AST_LOCK_SUCCESS) {
1753 ast_log(AST_LOG_WARNING, "Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR);
1755 goto module_reload_done;
1756 }
1757 }
1758
1761 const struct ast_module_info *info = cur->info;
1762
1763 if (name && resource_name_match(name, name_baselen, cur->resource)) {
1764 continue;
1765 }
1766
1767 if (!cur->flags.running || cur->flags.declined) {
1768 if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1770 }
1771 if (!name) {
1772 continue;
1773 }
1774 break;
1775 }
1776
1777 if (!info->reload) { /* cannot be reloaded */
1778 if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1780 }
1781 if (!name) {
1782 continue;
1783 }
1784 break;
1785 }
1786 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
1787 if (info->reload() == AST_MODULE_LOAD_SUCCESS) {
1789 } else if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1791 }
1792 if (name) {
1793 break;
1794 }
1795 }
1797
1800 }
1801module_reload_done:
1803 ast_sd_notify("READY=1");
1804
1805module_reload_exit:
1807 return res;
1808}
#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:291
static ast_mutex_t reloadlock
Definition: loader.c:631
static void queue_reload_request(const char *module)
Definition: loader.c:1591
static void publish_reload_message(const char *name, enum ast_module_reload_result result)
Definition: loader.c:1713
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_trylock(a)
Definition: lock.h:191
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:337
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::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 2925 of file loader.c.

2926{
2927 return support_level_map[support_level];
2928}
const char * support_level_map[]
Definition: loader.c:2918

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

769{
770 struct ast_module *mod = NULL;
771
772 /* it is assumed that the users list in the module structure
773 will already be empty, or we cannot have gotten to this
774 point
775 */
778 if (mod->info == info) {
780 break;
781 }
782 }
785
786 if (mod && !mod->usecount) {
787 /*
788 * We are intentionally leaking mod if usecount is not zero.
789 * This is necessary if the module is being forcefully unloaded.
790 * In addition module_destroy is not safe to run after exit()
791 * is called. ast_module_unregister is run during cleanup of
792 * the process when libc releases each module's shared object
793 * library.
794 */
795 ast_debug(5, "Unregistering module %s\n", info->name);
796 module_destroy(mod);
797 }
798}
#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:744

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

1567{
1568 struct reload_queue_item *item;
1569
1570 modules_loaded = 1;
1571
1573
1574 if (do_full_reload) {
1575 do_full_reload = 0;
1577 ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
1579 return;
1580 }
1581
1583 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
1584 ast_module_reload(item->module);
1585 ast_free(item);
1586 }
1587
1589}
#define LOG_NOTICE
static int do_full_reload
Definition: loader.c:638
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
Definition: loader.c:1721
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, 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 1407 of file loader.c.

1408{
1409 if (recursive) {
1410 /* Recursively unload dependents of this module and then load them back again */
1411 int res, i;
1412 struct ast_vector_const_string dependents;
1413 AST_VECTOR_INIT(&dependents, 0);
1414 res = auto_unload_resource(resource_name, force, recursive, &dependents);
1415 if (res) {
1416 AST_VECTOR_FREE(&dependents);
1417 return 1;
1418 }
1419 /* Start by loading the target again. */
1420 if (ast_load_resource(resource_name)) {
1421 ast_log(LOG_WARNING, "Failed to load module '%s' again automatically\n", resource_name);
1422 AST_VECTOR_FREE(&dependents);
1423 return -1;
1424 }
1425 res = 0;
1426 /* Finally, load again any modules we had to unload in order to refresh the target.
1427 * We must load modules in the reverse order that we unloaded them,
1428 * to preserve dependency requirements. */
1429 for (i = 0; i < AST_VECTOR_SIZE(&dependents); i++) {
1430 const char *depname = AST_VECTOR_GET(&dependents, i);
1431 int mres = ast_load_resource(depname);
1432 if (mres) {
1433 ast_log(LOG_WARNING, "Could not load module '%s' again automatically\n", depname);
1434 }
1435 res |= mres;
1436 }
1437 AST_VECTOR_FREE(&dependents);
1438 return res ? -1 : 0;
1439 }
1440
1441 /* Simple case: just unload and load the module again */
1442 if (ast_unload_resource(resource_name, force)) {
1443 return 1;
1444 }
1445 return ast_load_resource(resource_name);
1446}
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:1285
enum ast_module_load_result ast_load_resource(const char *resource_name)
Load a module.
Definition: loader.c:1978
#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 1448 of file loader.c.

1449{
1450 return auto_unload_resource(resource_name, force, 0, NULL);
1451}

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

2741{
2742 int total_mod_loaded = 0;
2743 struct module_vector alpha_module_list;
2744
2746
2747 if (!alpha_module_list_create(&alpha_module_list)) {
2748 int idx;
2749
2750 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2751 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2752
2753 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
2754 cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
2755 }
2756 }
2757
2759 AST_VECTOR_FREE(&alpha_module_list);
2760
2761 return total_mod_loaded;
2762}
static int alpha_module_list_create(struct module_vector *alpha_module_list)
Definition: loader.c:2720
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 2792 of file loader.c.

2798{
2799 int conditions_met = 0;
2800 struct module_vector alpha_module_list;
2801
2803
2804 if (!alpha_module_list_create(&alpha_module_list)) {
2805 int idx;
2806
2807 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2808 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2809
2810 conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
2811 cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
2812 condition);
2813 }
2814 }
2815
2817 AST_VECTOR_FREE(&alpha_module_list);
2818
2819 return conditions_met;
2820}

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

2769{
2770 int total_mod_loaded = 0;
2771 struct module_vector alpha_module_list;
2772
2774
2775 if (!alpha_module_list_create(&alpha_module_list)) {
2776 int idx;
2777
2778 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2779 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2780
2781 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
2782 cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
2783 }
2784 }
2785
2787 AST_VECTOR_FREE(&alpha_module_list);
2788
2789 return total_mod_loaded;
2790}

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

2699{
2700 /* Notify any module monitors that the use count for a
2701 resource has changed */
2702 struct loadupdate *m;
2703
2706 m->updater();
2708}

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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 1285 of file loader.c.

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

Definition at line 927 of file loader.c.

928{
929 struct ast_module *cur;
930 size_t resource_baselen = resource_name_baselen(resource);
931
932 if (do_lock) {
934 }
935
937 if (!resource_name_match(resource, resource_baselen, cur->resource)) {
938 break;
939 }
940 }
941
942 if (do_lock) {
944 }
945
946 return cur;
947}

References AST_DLLIST_LOCK, AST_DLLIST_TRAVERSE, AST_DLLIST_UNLOCK, ast_module::resource, resource_name_baselen(), and resource_name_match().

Referenced by ast_load_resource(), ast_module_check(), auto_unload_resource(), load_dlopen_missing(), load_resource(), loader_config_init(), module_deps_missing_recursive(), module_deps_process_reqlist(), and module_load_helper_on_file().

◆ get_name_from_resource()

static char * get_name_from_resource ( const char *  resource)
static

Definition at line 157 of file loader.c.

158{
159 int len;
160 const char *last_three;
161 char *mod_name;
162
163 if (!resource) {
164 return NULL;
165 }
166
167 len = strlen(resource);
168 if (len > 3) {
169 last_three = &resource[len-3];
170 if (!strcasecmp(last_three, ".so")) {
171 mod_name = ast_calloc(1, len - 2);
172 if (mod_name) {
173 ast_copy_string(mod_name, resource, len - 2);
174 return mod_name;
175 } else {
176 /* Unable to allocate memory. */
177 return NULL;
178 }
179 }
180 }
181
182 /* Resource is the name - happens when manually unloading a module. */
183 mod_name = ast_calloc(1, len + 1);
184 if (mod_name) {
185 ast_copy_string(mod_name, resource, len + 1);
186 return mod_name;
187 }
188
189 /* Unable to allocate memory. */
190 return NULL;
191}
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 1225 of file loader.c.

1226{
1227 struct ast_module *mod;
1228 int usecount = target->usecount;
1229
1230 /* Check the reffed_deps of each module to see if we're one of them. */
1233 const char *name;
1234 /* This module is dependent on the target.
1235 * If we can unload this module gracefully,
1236 * then that would decrement our use count.
1237 * If any single module could not be unloaded gracefully,
1238 * then we don't proceed. */
1239 int unloadable;
1240 if (AST_VECTOR_GET_CMP(dependents, ast_module_name(mod), !strcasecmp)) {
1241 /* Already in our list, we already checked this module,
1242 * and we gave it the green light. */
1243 ast_debug(3, "Skipping duplicate dependent %s\n", ast_module_name(mod));
1244 if (!--usecount) {
1245 break;
1246 }
1247 continue;
1248 }
1249 unloadable = graceful_unload_possible(mod, dependents);
1250 if (!unloadable) {
1251 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));
1252 return 0;
1253 }
1254 /* Insert at beginning, so later if we're loading modules again automatically, we can do so in the same order. */
1256 if (!name) {
1257 return 0;
1258 }
1259 ast_debug(3, "Found new dependent %s\n", ast_module_name(mod));
1260 if (AST_VECTOR_INSERT_AT(dependents, 0, name)) {
1261 ast_log(LOG_ERROR, "Failed to add module '%s' to vector\n", ast_module_name(mod));
1262 return 0;
1263 }
1264 if (!--usecount) {
1265 break;
1266 }
1267 }
1268 }
1269
1270 if (usecount) {
1271 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);
1272 return 0;
1273 }
1274 return 1;
1275}
#define LOG_ERROR
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:615
#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, 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 1810 of file loader.c.

1811{
1812 if (!mod->info->description) {
1813 module_load_error("Module '%s' does not provide a description.\n", mod->resource);
1814 return 1;
1815 }
1816
1817 if (!mod->info->key) {
1818 module_load_error("Module '%s' does not provide a license key.\n", mod->resource);
1819 return 1;
1820 }
1821
1822 if (verify_key((unsigned char *) mod->info->key)) {
1823 module_load_error("Module '%s' did not provide a valid license key.\n", mod->resource);
1824 return 1;
1825 }
1826
1827 if (!ast_strlen_zero(mod->info->buildopt_sum) &&
1828 strcmp(buildopt_sum, mod->info->buildopt_sum)) {
1829 module_load_error("Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
1830 module_load_error("Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
1831 return 1;
1832 }
1833
1834 return 0;
1835}
static char buildopt_sum[33]
Definition: loader.c:138
static void module_load_error(const char *fmt,...)
Definition: loader.c:269
static int verify_key(const unsigned char *key)
Definition: loader.c:890
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 981 of file loader.c.

982{
983 char fn[PATH_MAX] = "";
984 void *lib;
985
986 snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR,
987 resource_name);
988
989 lib = dlopen(fn, RTLD_LAZY | RTLD_NOLOAD);
990
991 if (lib) {
992 logged_dlclose(resource_name, lib);
993 return 1;
994 }
995
996 return 0;
997}
#define PATH_MAX
Definition: asterisk.h:40
static void logged_dlclose(const char *name, void *lib)
dlclose(), with failure logging.
Definition: loader.c:952
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 1060 of file loader.c.

1062{
1063 struct ast_module *mod;
1064
1066
1067 mod = ast_calloc(1, sizeof(*mod) + strlen(resource_in) + strlen(so_ext) + 1);
1068 if (!mod) {
1069 return NULL;
1070 }
1071
1072 sprintf(mod->resource, "%s%s", resource_in, so_ext); /* safe */
1073
1075 mod->lib = dlopen(filename, flags);
1076#if defined(HAVE_PERMANENT_DLOPEN)
1077 manual_mod_reg(mod->lib, mod->resource);
1078#endif
1080 struct ast_str *list;
1081 int c = 0;
1082 const char *dlerror_msg = ast_strdupa(S_OR(dlerror(), ""));
1083
1085 if (mod->lib) {
1086 module_load_error("Module '%s' did not register itself during load\n", resource_in);
1087 logged_dlclose(resource_in, mod->lib);
1088
1089 goto error_return;
1090 }
1091
1092 if (suppress_logging) {
1093 goto error_return;
1094 }
1095
1097 mod->lib = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
1098#if defined(HAVE_PERMANENT_DLOPEN)
1099 manual_mod_reg(mod->lib, mod->resource);
1100#endif
1103
1104 module_load_error("Error loading module '%s': %s\n", resource_in, dlerror_msg);
1105 logged_dlclose(resource_in, mod->lib);
1106
1107 goto error_return;
1108 }
1109
1110 list = ast_str_create(64);
1111 if (list) {
1112 if (module_post_register(mod)) {
1113 goto loaded_error;
1114 }
1115
1116 c = load_dlopen_missing(&list, &mod->requires);
1117 c += load_dlopen_missing(&list, &mod->enhances);
1118#ifndef OPTIONAL_API
1119 c += load_dlopen_missing(&list, &mod->optional_modules);
1120#endif
1121 }
1122
1123 if (list && ast_str_strlen(list)) {
1124 module_load_error("Error loading module '%s', missing %s: %s\n",
1125 resource_in, c == 1 ? "dependency" : "dependencies", ast_str_buffer(list));
1126 } else {
1127 module_load_error("Error loading module '%s': %s\n", resource_in, dlerror_msg);
1128 }
1129
1130loaded_error:
1131 ast_free(list);
1133
1134 return NULL;
1135
1136error_return:
1137 ast_free(mod);
1138
1139 return NULL;
1140 }
1141
1142 return mod;
1143}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define RTLD_LOCAL
Definition: loader.c:124
static int module_post_register(struct ast_module *mod)
Definition: loader.c:732
static int load_dlopen_missing(struct ast_str **list, struct ast_vector_string *deps)
Definition: loader.c:1030
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:298
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 1030 of file loader.c.

1031{
1032 int i;
1033 int c = 0;
1034
1035 for (i = 0; i < AST_VECTOR_SIZE(deps); i++) {
1036 const char *dep = AST_VECTOR_GET(deps, i);
1037 if (!find_resource(dep, 0)) {
1038 STR_APPEND_TEXT(dep, list);
1039 c++;
1040 }
1041 }
1042
1043 return c;
1044}
#define STR_APPEND_TEXT(txt, str)
Definition: loader.c:144

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

1146{
1147 char fn[PATH_MAX];
1148 struct ast_module *mod;
1149 size_t resource_in_len = strlen(resource_in);
1150 const char *so_ext = "";
1151
1152 if (resource_in_len < 4 || strcasecmp(resource_in + resource_in_len - 3, ".so")) {
1153 so_ext = ".so";
1154 }
1155
1156 snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, so_ext);
1157
1158 /* Try loading in quiet mode first with RTLD_LOCAL. The majority of modules do not
1159 * export symbols so this allows the least number of calls to dlopen. */
1160 mod = load_dlopen(resource_in, so_ext, fn, RTLD_NOW | RTLD_LOCAL, suppress_logging);
1161
1162 if (!mod || !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
1163 return mod;
1164 }
1165
1166 /* Close the module so we can reopen with correct flags. */
1167 logged_dlclose(resource_in, mod->lib);
1168
1169 return load_dlopen(resource_in, so_ext, fn, RTLD_NOW | RTLD_GLOBAL, 0);
1170}
#define RTLD_NOW
Definition: loader.c:120
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:1060
@ 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 2508 of file loader.c.

2509{
2510 struct load_order_entry *order;
2511 unsigned int load_count;
2512 struct load_order load_order;
2513 int res = 0;
2514 int modulecount = 0;
2515 int i;
2516 struct ast_module *cur;
2517#ifdef AST_XML_DOCS
2518 struct ast_str *warning_msg;
2519 char deprecated_in[33];
2520 char removed_in[33];
2521 char replacement[129];
2522#endif
2523 struct timeval start_time = ast_tvnow();
2524 struct timeval end_time;
2525 int64_t usElapsed;
2526
2527 ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
2528
2529#if defined(HAVE_PERMANENT_DLOPEN)
2531 info_list_obj_cmp_fn); /* must not be cleaned at shutdown */
2532 if (!info_list) {
2533 fprintf(stderr, "Module info list allocation failure.\n");
2534 return 1;
2535 }
2536#endif
2537
2540
2543
2545 if (res) {
2546 goto done;
2547 }
2548
2550 if (res) {
2551 goto done;
2552 }
2553
2554 load_count = 0;
2556 load_count++;
2557
2558 if (load_count)
2559 ast_log(LOG_NOTICE, "%u modules will be loaded.\n", load_count);
2560
2561 res = load_resource_list(&load_order, &modulecount);
2562 if (res == -1) {
2563 ast_log(LOG_WARNING, "Some non-required modules failed to load.\n");
2564 res = 0;
2565 }
2566
2567done:
2569 ast_free(order->resource);
2570 ast_free(order);
2571 }
2572
2573#ifdef AST_XML_DOCS
2574 warning_msg = ast_str_create(512);
2575#endif
2576
2578#ifdef AST_XML_DOCS
2579 char *mod_name = NULL;
2580 struct ast_xml_xpath_results *results;
2581#endif
2582
2583 if (!cur->flags.running || cur->flags.declined) {
2584 continue;
2585 }
2586
2587#ifdef AST_XML_DOCS
2588 mod_name = get_name_from_resource(cur->resource);
2589 if (!warning_msg || !mod_name) {
2590 /* If we can't allocate memory, we have bigger issues */
2591 ast_free(mod_name);
2592 continue;
2593 }
2594
2595 /* Clear out the previous values */
2596 deprecated_in[0] = removed_in[0] = replacement[0] = 0;
2597
2598 results = ast_xmldoc_query("/docs/module[@name='%s']", mod_name);
2599 if (results) {
2600 struct ast_xml_node *deprecated_node, *removed_node, *replacement_node;
2601 struct ast_xml_node *metadata_nodes = ast_xml_node_get_children(ast_xml_xpath_get_first_result(results));
2602
2603 deprecated_node = ast_xml_find_element(metadata_nodes, "deprecated_in", NULL, NULL);
2604 if (deprecated_node) {
2605 const char *result_tmp = ast_xml_get_text(deprecated_node);
2606 if (!ast_strlen_zero(result_tmp)) {
2607 ast_copy_string(deprecated_in, result_tmp, sizeof(deprecated_in));
2608 }
2609 }
2610
2611 removed_node = ast_xml_find_element(metadata_nodes, "removed_in", NULL, NULL);
2612 if (removed_node) {
2613 const char *result_tmp = ast_xml_get_text(removed_node);
2614 if (!ast_strlen_zero(result_tmp)) {
2615 ast_copy_string(removed_in, result_tmp, sizeof(removed_in));
2616 }
2617 }
2618
2619 replacement_node = ast_xml_find_element(metadata_nodes, "replacement", NULL, NULL);
2620 if (replacement_node) {
2621 const char *result_tmp = ast_xml_get_text(replacement_node);
2622 if (!ast_strlen_zero(result_tmp)) {
2623 ast_copy_string(replacement, result_tmp, sizeof(replacement));
2624 }
2625 }
2626
2628 }
2629
2630 ast_str_reset(warning_msg);
2631
2632 if (cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED || !ast_strlen_zero(deprecated_in)
2633 || !ast_strlen_zero(removed_in) || !ast_strlen_zero(replacement)) {
2634 int already_butted = 0;
2635
2636 ast_str_append(&warning_msg, -1, "Module '%s' has been loaded", mod_name);
2637 if (!ast_strlen_zero(deprecated_in)) {
2638 ast_str_append(&warning_msg, -1, " but %s deprecated in Asterisk version %s",
2639 cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED ? "was" : "will be", deprecated_in);
2640 already_butted = 1;
2641 }
2642
2643 if (!ast_strlen_zero(removed_in)) {
2644 ast_str_append(&warning_msg, -1, " %s will be removed in Asterisk version %s", already_butted ? "and" : "but", removed_in);
2645 } else {
2646 ast_str_append(&warning_msg, -1, " %s may be removed in a future release", already_butted ? "and" : "but");
2647 }
2648
2649 ast_str_append(&warning_msg, -1, ".");
2650
2651 if (!ast_strlen_zero(replacement)) {
2652 ast_str_append(&warning_msg, -1, " Its replacement is '%s'.", replacement);
2653 }
2654 }
2655
2656 if (ast_str_strlen(warning_msg)) {
2657 ast_log(LOG_WARNING, "%s\n", ast_str_buffer(warning_msg));
2658 }
2659
2660 ast_free(mod_name);
2661#else
2663 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);
2664 }
2665#endif
2666 }
2667
2668#ifdef AST_XML_DOCS
2669 ast_free(warning_msg);
2670#endif
2671
2673
2674
2675 for (i = 0; i < AST_VECTOR_SIZE(&startup_errors); i++) {
2676 char *str = AST_VECTOR_GET(&startup_errors, i);
2677
2678 ast_log(LOG_ERROR, "%s", str);
2679 ast_free(str);
2680 }
2682
2685
2686 end_time = ast_tvnow();
2687 usElapsed = ast_tvdiff_us(end_time, start_time);
2688
2689#ifdef AST_XML_DOCS
2690 ast_debug(1, "Loader time with AST_XML_DOCS: %" PRId64 ".%06" PRId64 "\n", usElapsed / 1000000, usElapsed % 1000000);
2691#else
2692 ast_debug(1, "Loader time without AST_XML_DOCS: %" PRId64 ".%06" PRId64 "\n", usElapsed / 1000000, usElapsed % 1000000);
2693#endif
2694
2695 return res;
2696}
#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:2271
static struct ast_vector_string startup_errors
Definition: loader.c:153
static struct ast_str * startup_error_builder
Definition: loader.c:154
static int loader_config_init(struct load_order *load_order)
Definition: loader.c:2384
static int loader_builtin_init(struct load_order *load_order)
Definition: loader.c:2349
static char * get_name_from_resource(const char *resource)
Definition: loader.c:157
@ 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:2576

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

1924{
1925 struct ast_module *mod;
1927
1928 if ((mod = find_resource(resource_name, 0))) {
1929 if (mod->flags.running) {
1930 ast_log(LOG_WARNING, "Module '%s' already loaded and running.\n", resource_name);
1932 }
1933 } else {
1934 mod = load_dynamic_module(resource_name, suppress_logging);
1935 if (!mod) {
1937 }
1938
1939 if (module_post_register(mod)) {
1940 goto prestart_error;
1941 }
1942 }
1943
1944 mod->flags.required |= required;
1945 mod->flags.preload |= preload;
1946
1947 if (inspect_module(mod)) {
1948 goto prestart_error;
1949 }
1950
1951 mod->flags.declined = 0;
1952
1953 if (module_priorities) {
1954 if (AST_VECTOR_ADD_SORTED(module_priorities, mod, module_vector_cmp)) {
1955 goto prestart_error;
1956 }
1958 } else {
1959 res = start_resource(mod);
1960 }
1961
1963 publish_load_message(resource_name, res);
1964 }
1965
1966 return res;
1967
1968prestart_error:
1969 module_load_error("Module '%s' could not be loaded.\n", resource_name);
1973 publish_load_message(resource_name, res);
1974 }
1975 return res;
1976}
int ast_shutdown_final(void)
Definition: asterisk.c:1872
static struct ast_module * load_dynamic_module(const char *resource_in, unsigned int suppress_logging)
Definition: loader.c:1145
static int module_vector_cmp(struct ast_module *a, struct ast_module *b)
Definition: loader.c:371
static unsigned int inspect_module(const struct ast_module *mod)
Definition: loader.c:1810
static enum ast_module_load_result start_resource(struct ast_module *mod)
Definition: loader.c:1837
static void publish_load_message(const char *name, enum ast_module_load_result result)
Definition: loader.c:1690
@ 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:328
unsigned int preload
Definition: loader.c:330

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

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

2350{
2351 struct ast_module *mod;
2352
2353 /*
2354 * All built-in modules have registered the first time, now it's time to complete
2355 * the registration and add them to the priority list.
2356 */
2357 loader_ready = 1;
2358
2360 /* ast_module_register doesn't finish when first run by built-in modules. */
2362 }
2363
2364 /* Add all built-in modules to the load order. */
2366 if (!mod->flags.builtin) {
2367 continue;
2368 }
2369
2370 /* Parse dependendencies from mod->info. */
2371 if (module_post_register(mod)) {
2372 return -1;
2373 }
2374
2375 /* Built-in modules are not preloaded, most have an early load priority. */
2376 if (!add_to_load_order(mod->resource, load_order, 0, 0, 1)) {
2377 return -1;
2378 }
2379 }
2380
2381 return 0;
2382}
#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:2012
void ast_module_register(const struct ast_module_info *info)
Definition: loader.c:659

References add_to_load_order(), AST_DLLIST_REMOVE_HEAD, AST_DLLIST_TRAVERSE, ast_module_register(), ast_module::builtin, builtin_module_list, 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 2384 of file loader.c.

2385{
2386 int res = -1;
2387 struct load_order_entry *order;
2388 struct ast_config *cfg;
2389 struct ast_variable *v;
2390 struct ast_flags config_flags = { 0 };
2391
2392 cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
2394 ast_log(LOG_WARNING, "'%s' invalid or missing.\n", AST_MODULE_CONFIG);
2395
2396 return -1;
2397 }
2398
2399 /* first, find all the modules we have been explicitly requested to load */
2400 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
2401 int required;
2402 int preload = 0;
2403
2404 if (!strncasecmp(v->name, "preload", strlen("preload"))) {
2405 preload = 1;
2406 if (!strcasecmp(v->name, "preload")) {
2407 required = 0;
2408 } else if (!strcasecmp(v->name, "preload-require")) {
2409 required = 1;
2410 } else {
2411 ast_log(LOG_ERROR, "Unknown configuration option '%s'", v->name);
2412 goto done;
2413 }
2414 } else if (!strcasecmp(v->name, "load")) {
2415 required = 0;
2416 } else if (!strcasecmp(v->name, "require")) {
2417 required = 1;
2418 } else if (!strcasecmp(v->name, "noload") || !strcasecmp(v->name, "autoload")) {
2419 continue;
2420 } else {
2421 ast_log(LOG_ERROR, "Unknown configuration option '%s'", v->name);
2422 goto done;
2423 }
2424
2425 if (required) {
2426 ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
2427 }
2428
2429 if (!add_to_load_order(v->value, load_order, required, preload, 0)) {
2430 goto done;
2431 }
2432 }
2433
2434 /* check if 'autoload' is on */
2435 if (ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
2436 /* if we are allowed to load dynamic modules, scan the directory for
2437 for all available modules and add them as well */
2438 DIR *dir = opendir(ast_config_AST_MODULE_DIR);
2439 struct dirent *dirent;
2440
2441 if (dir) {
2442 while ((dirent = readdir(dir))) {
2443 int ld = strlen(dirent->d_name);
2444
2445 /* Must end in .so to load it. */
2446
2447 if (ld < 4)
2448 continue;
2449
2450 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
2451 continue;
2452
2453 /* if there is already a module by this name in the module_list,
2454 skip this file */
2455 if (find_resource(dirent->d_name, 0))
2456 continue;
2457
2458 if (!add_to_load_order(dirent->d_name, load_order, 0, 0, 0)) {
2459 closedir(dir);
2460 goto done;
2461 }
2462 }
2463
2464 closedir(dir);
2465 } else {
2466 ast_log(LOG_ERROR, "Unable to open modules directory '%s'.\n", ast_config_AST_MODULE_DIR);
2467 goto done;
2468 }
2469 }
2470
2471 /* now scan the config for any modules we are prohibited from loading and
2472 remove them from the load order */
2473 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
2474 size_t baselen;
2475
2476 if (strcasecmp(v->name, "noload")) {
2477 continue;
2478 }
2479
2480 baselen = resource_name_baselen(v->value);
2482 if (!resource_name_match(v->value, baselen, order->resource)) {
2483 if (order->builtin) {
2484 ast_log(LOG_ERROR, "%s is a built-in module, you cannot specify 'noload'.\n", v->value);
2485 goto done;
2486 }
2487
2488 if (order->required) {
2489 ast_log(LOG_ERROR, "%s is configured with '%s' and 'noload', this is impossible.\n",
2490 v->value, order->preload ? "preload-require" : "require");
2491 goto done;
2492 }
2494 ast_free(order->resource);
2495 ast_free(order);
2496 }
2497 }
2499 }
2500
2501 res = 0;
2502done:
2503 ast_config_destroy(cfg);
2504
2505 return res;
2506}
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:3322
#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:784
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 1673 of file loader.c.

1674{
1675 int i;
1676 for (i = 0; i < ARRAY_LEN(load_results); i++) {
1677 if (load_results[i].result == result) {
1678 return load_results[i].name;
1679 }
1680 }
1681
1682 ast_log(LOG_WARNING, "Failed to find correct load result status. result %d\n", result);
1684}
static PGresult * result
Definition: cel_pgsql.c:84
static const struct load_results_map load_results[]
Definition: loader.c:344
#define AST_MODULE_LOAD_UNKNOWN_STRING
Definition: loader.c:351
const char * name
Definition: loader.c:341
#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 952 of file loader.c.

953{
954 char *error;
955
956 if (!lib) {
957 return;
958 }
959
960 /* Clear any existing error */
961 dlerror();
962 if (dlclose(lib)) {
963 error = dlerror();
964 ast_log(AST_LOG_ERROR, "Failure in dlclose for module '%s': %s\n",
965 S_OR(name, "unknown"), S_OR(error, "Unknown error"));
966#if defined(HAVE_PERMANENT_DLOPEN)
967 } else {
968 manual_mod_unreg(name);
969#endif
970 }
971}
#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 566 of file loader.c.

567{
568 int i = 0;
569 int res = -1;
570 struct ast_vector_const_string localdeps;
571 struct ast_module *dep;
572
573 /*
574 * localdeps stores a copy of all dependencies that mod could not reference.
575 * First we discard modules that we've already found. We add all newly found
576 * modules to the missingdeps vector then scan them recursively. This will
577 * ensure we quickly run out of stuff to do.
578 */
579 AST_VECTOR_INIT(&localdeps, 0);
580 if (module_deps_reference(mod, &localdeps)) {
581 goto clean_return;
582 }
583
584 while (i < AST_VECTOR_SIZE(&localdeps)) {
585 dep = find_resource(AST_VECTOR_GET(&localdeps, i), 0);
586 if (!dep) {
587 goto clean_return;
588 }
589
590 if (AST_VECTOR_GET_CMP(missingdeps, dep, AST_VECTOR_ELEM_DEFAULT_CMP)) {
591 /* Skip common dependency. We have already searched it. */
592 AST_VECTOR_REMOVE(&localdeps, i, 0);
593 } else {
594 /* missingdeps is the real list so keep it sorted. */
595 if (AST_VECTOR_ADD_SORTED(missingdeps, dep, module_vector_cmp)) {
596 goto clean_return;
597 }
598 i++;
599 }
600 }
601
602 res = 0;
603 for (i = 0; !res && i < AST_VECTOR_SIZE(&localdeps); i++) {
604 dep = find_resource(AST_VECTOR_GET(&localdeps, i), 0);
605 /* We've already confirmed dep is loaded in the first loop. */
606 res = module_deps_missing_recursive(dep, missingdeps);
607 }
608
609clean_return:
610 AST_VECTOR_FREE(&localdeps);
611
612 return res;
613}
static int module_deps_reference(struct ast_module *mod, struct ast_vector_const_string *missing)
Definition: loader.c:534
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:566
#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 485 of file loader.c.

488{
489 int idx;
490
491 for (idx = 0; idx < AST_VECTOR_SIZE(vec); idx++) {
492 const char *depname = AST_VECTOR_GET(vec, idx);
493 struct ast_module *dep = find_resource(depname, 0);
494
495 if (!dep || !dep->flags.running) {
496 if (isoptional && !dep) {
497 continue;
498 }
499
500 if (missing && !AST_VECTOR_APPEND(missing, depname)) {
501 continue;
502 }
503
504 return -1;
505 }
506
507 if (module_reffed_deps_add(mod, dep, missing)) {
508 return -1;
509 }
510
511 if (ref_enhancers && module_reffed_deps_add_dep_enhancers(mod, dep, missing)) {
512 return -1;
513 }
514 }
515
516 return 0;
517}
static int module_reffed_deps_add(struct ast_module *mod, struct ast_module *dep, struct ast_vector_const_string *missing)
Definition: loader.c:416
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:448
#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 534 of file loader.c.

535{
536 int res = 0;
537
538 /* Grab references to modules we enhance but not other enhancements. */
539 res |= module_deps_process_reqlist(mod, &mod->enhances, missing, 0, 0);
540
541 /* Grab references to modules we require plus enhancements. */
542 res |= module_deps_process_reqlist(mod, &mod->requires, missing, 1, 0);
543
544 /* Grab references to optional modules including enhancements. */
545 res |= module_deps_process_reqlist(mod, &mod->optional_modules, missing, 1, 1);
546
547 return res;
548}
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:485

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

745{
748
751
754
755 /* Release references to all dependencies. */
758
761 if (mod->flags.builtin) {
762 ast_std_free(mod);
763 } else {
764 ast_free(mod);
765 }
766}
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 269 of file loader.c.

270{
271 char *copy = NULL;
272 va_list ap;
273
274 va_start(ap, fmt);
280 ast_free(copy);
281 }
282 } else {
283 ast_log_ap(LOG_ERROR, fmt, ap);
284 }
285 va_end(ap);
286}
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:2462
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 1515 of file loader.c.

1516{
1517 struct module_load_word word_l = {
1518 .word = word,
1519 .len = strlen(word),
1520 .moddir_len = strlen(ast_config_AST_MODULE_DIR),
1521 };
1522
1526}
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:1274
static int module_load_helper_on_file(const char *dir_name, const char *filename, void *obj)
Definition: loader.c:1483
const char * word
Definition: loader.c:1478

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

1484{
1485 struct module_load_word *word = obj;
1486 struct ast_module *mod;
1487 char *filename_merged = NULL;
1488
1489 /* dir_name will never be shorter than word->moddir_len. */
1490 dir_name += word->moddir_len;
1491 if (!ast_strlen_zero(dir_name)) {
1492 ast_assert(dir_name[0] == '/');
1493
1494 dir_name += 1;
1495 if (ast_asprintf(&filename_merged, "%s/%s", dir_name, filename) < 0) {
1496 /* If we can't allocate the string just give up! */
1497 return -1;
1498 }
1499 filename = filename_merged;
1500 }
1501
1502 if (!strncasecmp(filename, word->word, word->len)) {
1503 /* Don't list files that are already loaded! */
1504 mod = find_resource(filename, 0);
1505 if (!mod || !mod->flags.running) {
1507 }
1508 }
1509
1510 ast_free(filename_merged);
1511
1512 return 0;
1513}
#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 1453 of file loader.c.

1454{
1455 switch (type) {
1457 return !mod->usecount && mod->flags.running && !mod->flags.declined;
1458
1460 return mod->flags.running && mod->info->reload;
1461
1463 return mod->flags.running;
1464
1466 /* if we have a 'struct ast_module' then we're loaded. */
1467 return 1;
1468 default:
1469 /* This function is not called for AST_MODULE_HELPER_LOAD. */
1470 /* Unknown ast_module_helper_type. Assume it doesn't match. */
1471 ast_assert(0);
1472
1473 return 0;
1474 }
1475}
@ 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 732 of file loader.c.

733{
734 int res;
735
736 /* Split lists from mod->info. */
737 res = ast_vector_string_split(&mod->requires, mod->info->requires, ",", 0, strcasecmp);
738 res |= ast_vector_string_split(&mod->optional_modules, mod->info->optional_modules, ",", 0, strcasecmp);
739 res |= ast_vector_string_split(&mod->enhances, mod->info->enhances, ",", 0, strcasecmp);
740
741 return res;
742}
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:392

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

418{
419 if (!dep->flags.running) {
420 return !missing ? -1 : AST_VECTOR_APPEND(missing, dep->info->name);
421 }
422
424 /* Skip duplicate. */
425 return 0;
426 }
427
428 if (AST_VECTOR_APPEND(&mod->reffed_deps, dep)) {
429 return -1;
430 }
431
432 ast_module_ref(dep);
433
434 return 0;
435}
#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 448 of file loader.c.

450{
451 struct ast_module *cur;
452
454 if (cur->flags.declined) {
455 continue;
456 }
457
458 if (!AST_VECTOR_GET_CMP(&cur->enhances, dep->info->name, !strcasecmp)) {
459 /* dep is not enhanced by cur. */
460 continue;
461 }
462
463 /* dep is enhanced by cur, therefore mod requires cur. */
464 if (module_reffed_deps_add(mod, cur, missing)) {
465 return -1;
466 }
467 }
468
469 return 0;
470}

References AST_DLLIST_TRAVERSE, AST_VECTOR_GET_CMP, ast_module::declined, ast_module::enhances, 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 371 of file loader.c.

372{
373 int preload_diff = (int)b->flags.preload - (int)a->flags.preload;
374 /* if load_pri is not set, default is 128. Lower is better */
375 int a_pri = ast_test_flag(a->info, AST_MODFLAG_LOAD_ORDER)
376 ? a->info->load_pri : AST_MODPRI_DEFAULT;
377 int b_pri = ast_test_flag(b->info, AST_MODFLAG_LOAD_ORDER)
378 ? b->info->load_pri : AST_MODPRI_DEFAULT;
379
380 if (preload_diff) {
381 /* -1 preload a but not b */
382 /* 0 preload both or neither */
383 /* 1 preload b but not a */
384 return preload_diff;
385 }
386
387 /*
388 * Returns comparison values for a vector sorted by priority.
389 * <0 a_pri < b_pri
390 * =0 a_pri == b_pri
391 * >0 a_pri > b_pri
392 */
393 return a_pri - b_pri;
394}
@ 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 366 of file loader.c.

367{
368 return strcasecmp(a->resource, b->resource);
369}

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

1173{
1174 struct ast_module *mod;
1175 int somethingchanged;
1176 int res;
1177
1179
1180 /*!\note Some resources, like timers, are started up dynamically, and thus
1181 * may be still in use, even if all channels are dead. We must therefore
1182 * check the usecount before asking modules to unload. */
1183 do {
1184 /* Reset flag before traversing the list */
1185 somethingchanged = 0;
1186
1188 if (mod->usecount) {
1189 ast_debug(1, "Passing on %s: its use count is %d\n",
1190 mod->resource, mod->usecount);
1191 continue;
1192 }
1194 if (mod->flags.running && !mod->flags.declined && mod->info->unload) {
1195 ast_verb(4, "Unloading %s\n", mod->resource);
1196 mod->info->unload();
1197 }
1198 module_destroy(mod);
1199 somethingchanged = 1;
1200 }
1202 if (!somethingchanged) {
1204 if (mod->flags.keepuntilshutdown) {
1205 ast_module_unref(mod);
1206 mod->flags.keepuntilshutdown = 0;
1207 somethingchanged = 1;
1208 }
1209 }
1210 }
1211 } while (somethingchanged);
1212
1215
1216 return !res;
1217}
#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::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 875 of file loader.c.

876{
877 int x, pos;
878 char buf[256]; /* large enough so we don't have to worry */
879
880 for (pos = 0, x = 0; x < 16; x++)
881 pos += sprintf(buf + pos, " %02hhx", *d++);
882
883 ast_debug(1, "Unexpected signature:%s\n", buf);
884
885 return 0;
886}
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 1690 of file loader.c.

1691{
1692 const char *status;
1693
1695
1697}
jack_status_t status
Definition: app_jack.c:146
static void publish_load_message_type(const char *type, const char *name, const char *status)
Definition: loader.c:1634
static const char * loadresult2str(enum ast_module_load_result result)
Definition: loader.c:1673

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

1635{
1637 RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
1638 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1639 RAII_VAR(struct ast_json *, event_object, NULL, ast_json_unref);
1640
1641 ast_assert(type != NULL);
1644
1646 return;
1647 }
1648
1649 event_object = ast_json_pack("{s:s, s:s}",
1650 "Module", name,
1651 "Status", status);
1652 json_object = ast_json_pack("{s:s, s:i, s:o}",
1653 "type", type,
1654 "class_type", EVENT_FLAG_SYSTEM,
1655 "event", ast_json_ref(event_object));
1656 if (!json_object) {
1657 return;
1658 }
1659
1660 payload = ast_json_payload_create(json_object);
1661 if (!payload) {
1662 return;
1663 }
1664
1666 if (!message) {
1667 return;
1668 }
1669
1671}
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:453
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:1512
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 1713 of file loader.c.

1714{
1715 char res_buffer[8];
1716
1717 snprintf(res_buffer, sizeof(res_buffer), "%u", result);
1718 publish_load_message_type("Reload", S_OR(name, "All"), res_buffer);
1719}

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

1704{
1706}

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

1592{
1593 struct reload_queue_item *item;
1594
1596
1597 if (do_full_reload) {
1599 return;
1600 }
1601
1602 if (ast_strlen_zero(module)) {
1603 /* A full reload request (when module is NULL) wipes out any previous
1604 reload requests and causes the queue to ignore future ones */
1606 ast_free(item);
1607 }
1608 do_full_reload = 1;
1609 } else {
1610 /* No reason to add the same module twice */
1612 if (!strcasecmp(item->module, module)) {
1614 return;
1615 }
1616 }
1617 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
1618 if (!item) {
1619 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
1621 return;
1622 }
1623 strcpy(item->module, module);
1625 }
1627}
char module[0]
Definition: loader.c:635

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

2078{
2079 struct module_vector missingdeps;
2080 struct ast_vector_const_string localdeps;
2081 int i = 0;
2082 int res = -1;
2083
2084 mod->flags.declined = 1;
2085 if (mod->flags.required) {
2086 module_load_error("Required module %s declined to load.\n", ast_module_name(mod));
2087
2088 return -2;
2089 }
2090
2091 module_load_error("%s declined to load.\n", ast_module_name(mod));
2092
2093 if (!*printmissing) {
2094 *printmissing = ast_str_create(64);
2095 if (!*printmissing) {
2096 return -1;
2097 }
2098 } else {
2099 ast_str_reset(*printmissing);
2100 }
2101
2102 AST_VECTOR_INIT(&missingdeps, 0);
2103 AST_VECTOR_INIT(&localdeps, 0);
2104
2105 /* Decline everything that depends on 'mod' from resources so we can
2106 * print a concise list. */
2107 while (res != -2 && i < AST_VECTOR_SIZE(resources)) {
2108 struct ast_module *dep = AST_VECTOR_GET(resources, i);
2109 i++;
2110
2112 if (dep->flags.declined || module_deps_missing_recursive(dep, &missingdeps)) {
2113 continue;
2114 }
2115
2116 if (AST_VECTOR_GET_CMP(&missingdeps, mod, AST_VECTOR_ELEM_DEFAULT_CMP)) {
2117 dep->flags.declined = 1;
2118 if (dep->flags.required) {
2119 module_load_error("Cannot load required module %s that depends on %s\n",
2120 ast_module_name(dep), ast_module_name(mod));
2121 res = -2;
2122 } else {
2123 AST_VECTOR_APPEND(&localdeps, ast_module_name(dep));
2124 }
2125 }
2126 }
2127 AST_VECTOR_FREE(&missingdeps);
2128
2129 if (res != -2 && AST_VECTOR_SIZE(&localdeps)) {
2130 AST_VECTOR_CALLBACK_VOID(&localdeps, STR_APPEND_TEXT, printmissing);
2131 module_load_error("Declined modules which depend on %s: %s\n",
2132 ast_module_name(mod), ast_str_buffer(*printmissing));
2133 }
2134 AST_VECTOR_FREE(&localdeps);
2135
2136 return res;
2137}
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 907 of file loader.c.

908{
909 size_t len = strlen(name);
910
911 if (len > 3 && !strcasecmp(name + len - 3, ".so")) {
912 return len - 3;
913 }
914
915 return len;
916}

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

919{
920 if (baselen1 != resource_name_baselen(name2)) {
921 return -1;
922 }
923
924 return strncasecmp(name1, name2, baselen1);
925}

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

1838{
1839 char tmp[256];
1840 enum ast_module_load_result res;
1841
1842 if (mod->flags.running) {
1844 }
1845
1846 if (!mod->info->load) {
1847 mod->flags.declined = 1;
1848
1850 }
1851
1852 if (module_deps_reference(mod, NULL)) {
1853 struct module_vector missing;
1854 int i;
1855
1856 AST_VECTOR_INIT(&missing, 0);
1857 if (module_deps_missing_recursive(mod, &missing)) {
1858 module_load_error("%s has one or more unknown dependencies.\n", mod->info->name);
1859 }
1860 for (i = 0; i < AST_VECTOR_SIZE(&missing); i++) {
1861 module_load_error("%s loaded before dependency %s!\n", mod->info->name,
1862 AST_VECTOR_GET(&missing, i)->info->name);
1863 }
1864 AST_VECTOR_FREE(&missing);
1865
1867 }
1868
1869 if (!ast_fully_booted) {
1870 ast_verb(4, "Loading %s.\n", mod->resource);
1871 }
1872 res = mod->info->load();
1873
1874 switch (res) {
1876 if (!ast_fully_booted) {
1877 ast_verb(5, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
1878 } else {
1879 ast_verb(4, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
1880 }
1881
1882 mod->flags.running = 1;
1883 if (mod->flags.builtin) {
1884 /* Built-in modules cannot be unloaded. */
1886 }
1887
1889 break;
1891 mod->flags.declined = 1;
1892 if (mod->flags.required) {
1894 }
1895 break;
1897 mod->flags.declined = 1;
1898 break;
1899 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
1901 break;
1902 }
1903
1904 /* Make sure the newly started module is at the end of the list */
1909
1910 return res;
1911}
#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, term_color(), and tmp().

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

2049{
2050 enum ast_module_load_result lres;
2051
2052 /* Try to grab required references. */
2053 if (module_deps_reference(mod, NULL)) {
2054 /* We're likely to retry so not an error. */
2055 ast_debug(1, "Module %s is missing dependencies\n", mod->resource);
2056 return AST_MODULE_LOAD_SKIP;
2057 }
2058
2059 lres = start_resource(mod);
2060 ast_debug(3, "START: %-46s[%d] %d\n",
2061 mod->resource,
2063 lres);
2064
2065 if (lres == AST_MODULE_LOAD_SUCCESS) {
2066 (*count)++;
2067 } else if (lres == AST_MODULE_LOAD_FAILURE) {
2068 module_load_error("*** Failed to load %smodule %s\n",
2069 mod->flags.required ? "required " : "",
2070 mod->resource);
2071 }
2072
2073 return lres;
2074}
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 2139 of file loader.c.

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

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

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

891{
892 struct MD5Context c;
893 unsigned char digest[16];
894
895 MD5Init(&c);
896 MD5Update(&c, key, strlen((char *)key));
897 MD5Final(digest, &c);
898
899 if (key_matches(expected_key, digest))
900 return 0;
901
902 printdigest(digest);
903
904 return -1;
905}
static const unsigned char expected_key[]
Definition: loader.c:134
static int printdigest(const unsigned char *d)
Definition: loader.c:875
#define key_matches(a, b)
Definition: loader.c:888
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[16], struct MD5Context *context)
Definition: md5.c:120
Definition: md5.h:26

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

Referenced by inspect_module().

◆ builtin_module_list

struct module_list builtin_module_list
static

Definition at line 364 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 638 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 134 of file loader.c.

Referenced by verify_key().

◆ load_results

const struct load_results_map load_results[]
static

Definition at line 344 of file loader.c.

Referenced by loadresult2str().

◆ loader_ready

unsigned int loader_ready
static

Definition at line 150 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 291 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 631 of file loader.c.

Referenced by ast_module_reload().

◆ resource_being_loaded

struct ast_module* volatile resource_being_loaded
static

Definition at line 650 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 154 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 153 of file loader.c.

Referenced by load_modules(), and module_load_error().

◆ support_level_map

const char* support_level_map[]

Definition at line 2918 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