Asterisk - The Open Source Telephony Project GIT-master-a358458
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_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 struct ast_modulefind_resource (const char *resource, int do_lock)
 
static char * get_name_from_resource (const char *resource)
 
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 2714 of file loader.c.

2715{
2716 if (!mod) {
2717 return NULL;
2718 }
2719
2720 if (mod->ref_debug) {
2721 __ao2_ref(mod->ref_debug, +1, "", file, line, func);
2722 }
2723
2726
2727 return mod;
2728}
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:2544
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 2730 of file loader.c.

2732{
2733 if (!mod || !mod->flags.running) {
2734 return NULL;
2735 }
2736
2737 return __ast_module_ref(mod, file, line, func);
2738}
struct ast_module * __ast_module_ref(struct ast_module *mod, const char *file, int line, const char *func)
Definition: loader.c:2714
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 2740 of file loader.c.

2741{
2742 if (!mod || mod->flags.keepuntilshutdown) {
2743 return;
2744 }
2745
2746 __ast_module_ref(mod, file, line, func);
2747 mod->flags.keepuntilshutdown = 1;
2748}
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 2750 of file loader.c.

2751{
2752 if (!mod) {
2753 return;
2754 }
2755
2756 if (mod->ref_debug) {
2757 __ao2_ref(mod->ref_debug, -1, "", file, line, func);
2758 }
2759
2762}

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:2471
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1143
#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 ast_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 1858 of file loader.c.

1859{
1860 struct load_order_entry *order;
1861 size_t resource_baselen = resource_name_baselen(resource);
1862
1864 if (!resource_name_match(resource, resource_baselen, order->resource)) {
1865 /* Make sure we have the proper setting for the required field
1866 (we might have both load= and required= lines in modules.conf) */
1867 order->required |= required;
1868 order->preload |= preload;
1869 return order;
1870 }
1871 }
1872
1873 order = ast_calloc(1, sizeof(*order));
1874 if (!order) {
1875 return NULL;
1876 }
1877
1878 order->resource = ast_strdup(resource);
1879 if (!order->resource) {
1880 ast_free(order);
1881
1882 return NULL;
1883 }
1884 order->required = required;
1885 order->preload = preload;
1886 order->builtin = builtin;
1888
1889 return order;
1890}
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:1848
int builtin
Definition: loader.c:1852
int required
Definition: loader.c:1850
int preload
Definition: loader.c:1851
char * resource
Definition: loader.c:1849

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

2567{
2568 struct ast_module *cur;
2569
2570 if (AST_VECTOR_INIT(alpha_module_list, 32)) {
2571 return -1;
2572 }
2573
2575 if (AST_VECTOR_ADD_SORTED(alpha_module_list, cur, module_vector_strcasecmp)) {
2576 return -1;
2577 }
2578 }
2579
2580 return 0;
2581}
#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 1824 of file loader.c.

1825{
1826 struct ast_module *mod;
1827 enum ast_module_load_result res;
1828
1829 /* If we're trying to load a module that previously declined to load,
1830 * transparently unload it first so we dlclose, then dlopen it afresh.
1831 * Otherwise, we won't actually load a (potentially) updated module. */
1832 mod = find_resource(resource_name, 0);
1833 if (mod && mod->flags.declined) {
1834 ast_debug(1, "Module %s previously declined to load, unloading it first before loading again\n", resource_name);
1835 ast_unload_resource(resource_name, 0);
1836 }
1837
1839 res = load_resource(resource_name, 0, NULL, 0, 0);
1840 if (!res) {
1841 ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);
1842 }
1844
1845 return res;
1846}
#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:1768
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
Unload a module.
Definition: loader.c:1219
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(), handle_load(), handle_refresh(), 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 2682 of file loader.c.

2683{
2684 struct loadupdate *tmp;
2685
2686 if (!(tmp = ast_malloc(sizeof(*tmp))))
2687 return -1;
2688
2689 tmp->updater = v;
2693
2694 return 0;
2695}
#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 2697 of file loader.c.

2698{
2699 struct loadupdate *cur;
2700
2703 if (cur->updater == v) {
2705 break;
2706 }
2707 }
2710
2711 return cur ? 0 : -1;
2712}
#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 2669 of file loader.c.

2670{
2671 struct ast_module *cur;
2672
2673 if (ast_strlen_zero(name))
2674 return 0; /* FALSE */
2675
2676 cur = find_resource(name, 1);
2677
2678 return (cur != NULL);
2679}
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 1374 of file loader.c.

1375{
1376 struct ast_module *mod;
1377 int which = 0;
1378 int wordlen = strlen(word);
1379 char *ret = NULL;
1380
1381 if (pos != rpos) {
1382 return NULL;
1383 }
1384
1385 /* Tab completion can't be used during startup, or CLI and loader will deadlock. */
1387 return NULL;
1388 }
1389
1392
1393 return NULL;
1394 }
1395
1398 if (!module_matches_helper_type(mod, type)) {
1399 continue;
1400 }
1401
1402 if (!strncasecmp(word, mod->resource, wordlen) && ++which > state) {
1403 ret = ast_strdup(mod->resource);
1404 break;
1405 }
1406 }
1408
1409 return ret;
1410}
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:1299
static void module_load_helper(const char *word)
Definition: loader.c:1361
@ 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:350
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(), 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 1567 of file loader.c.

1568{
1569 struct ast_module *cur;
1571 size_t name_baselen = name ? resource_name_baselen(name) : 0;
1572
1573 /* If we aren't fully booted, we just pretend we reloaded but we queue this
1574 up to run once we are booted up. */
1575 if (!modules_loaded) {
1578 goto module_reload_exit;
1579 }
1580
1582 ast_verb(3, "The previous reload command didn't finish yet\n");
1584 goto module_reload_exit;
1585 }
1586 ast_sd_notify("RELOAD=1");
1588
1590 int try;
1591 int lockres;
1592 for (try = 1, lockres = AST_LOCK_TIMEOUT; try < 6 && (lockres == AST_LOCK_TIMEOUT); try++) {
1594 if (lockres == AST_LOCK_TIMEOUT) {
1595 ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try);
1596 }
1597 }
1598 if (lockres != AST_LOCK_SUCCESS) {
1599 ast_log(AST_LOG_WARNING, "Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR);
1601 goto module_reload_done;
1602 }
1603 }
1604
1607 const struct ast_module_info *info = cur->info;
1608
1609 if (name && resource_name_match(name, name_baselen, cur->resource)) {
1610 continue;
1611 }
1612
1613 if (!cur->flags.running || cur->flags.declined) {
1614 if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1616 }
1617 if (!name) {
1618 continue;
1619 }
1620 break;
1621 }
1622
1623 if (!info->reload) { /* cannot be reloaded */
1624 if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1626 }
1627 if (!name) {
1628 continue;
1629 }
1630 break;
1631 }
1632 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
1633 if (info->reload() == AST_MODULE_LOAD_SUCCESS) {
1635 } else if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1637 }
1638 if (name) {
1639 break;
1640 }
1641 }
1643
1646 }
1647module_reload_done:
1649 ast_sd_notify("READY=1");
1650
1651module_reload_exit:
1653 return res;
1654}
#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:2604
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2620
#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:1437
static void publish_reload_message(const char *name, enum ast_module_reload_result result)
Definition: loader.c:1559
#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 2771 of file loader.c.

2772{
2773 return support_level_map[support_level];
2774}
const char * support_level_map[]
Definition: loader.c:2764

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

1413{
1414 struct reload_queue_item *item;
1415
1416 modules_loaded = 1;
1417
1419
1420 if (do_full_reload) {
1421 do_full_reload = 0;
1423 ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
1425 return;
1426 }
1427
1429 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
1430 ast_module_reload(item->module);
1431 ast_free(item);
1432 }
1433
1435}
#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:1567
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_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 1219 of file loader.c.

1220{
1221 struct ast_module *mod;
1222 int res = -1;
1223 int error = 0;
1224
1226
1227 if (!(mod = find_resource(resource_name, 0))) {
1229 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
1230 return -1;
1231 }
1232
1233 if (!mod->flags.running || mod->flags.declined) {
1234 /* If the user asks to unload a module that didn't load, obey.
1235 * Otherwise, we never dlclose() modules that fail to load,
1236 * which means if the module (shared object) is updated,
1237 * we can't load the updated module since we never dlclose()'d it.
1238 * Accordingly, obey the unload request so we can load the module
1239 * from scratch next time.
1240 */
1241 ast_log(LOG_NOTICE, "Unloading module '%s' that previously declined to load\n", resource_name);
1242 error = 0;
1243 res = 0;
1244 goto exit; /* Skip all the intervening !error checks, only the last one is relevant. */
1245 }
1246
1247 if (!error && (mod->usecount > 0)) {
1248 if (force)
1249 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n",
1250 resource_name, mod->usecount);
1251 else {
1252 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
1253 mod->usecount);
1254 error = 1;
1255 }
1256 }
1257
1258 if (!error) {
1259 /* Request any channels attached to the module to hangup. */
1261
1262 ast_verb(4, "Unloading %s\n", mod->resource);
1263 res = mod->info->unload();
1264 if (res) {
1265 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
1266 if (force <= AST_FORCE_FIRM) {
1267 error = 1;
1268 } else {
1269 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
1270 }
1271 }
1272
1273 if (!error) {
1274 /*
1275 * Request hangup on any channels that managed to get attached
1276 * while we called the module unload function.
1277 */
1279 sched_yield();
1280 }
1281 }
1282
1283 if (!error)
1284 mod->flags.running = mod->flags.declined = 0;
1285
1286exit:
1288
1289 if (!error) {
1291 ast_test_suite_event_notify("MODULE_UNLOAD", "Message: %s", resource_name);
1293 publish_unload_message(resource_name, "Success");
1294 }
1295
1296 return res;
1297}
static void publish_unload_message(const char *name, const char *status)
Definition: loader.c:1549
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
@ AST_FORCE_FIRM
Definition: module.h:63
int(* unload)(void)
Definition: module.h:348
int error(const char *format,...)
Definition: utils/frame.c:999

References __ast_module_user_hangup_all(), AST_DLLIST_LOCK, AST_DLLIST_UNLOCK, AST_FORCE_FIRM, ast_log, ast_test_suite_event_notify, ast_update_use_count(), ast_verb, ast_module::declined, error(), find_resource(), ast_module::flags, 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_ari_asterisk_unload_module(), ast_load_resource(), handle_refresh(), 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 2583 of file loader.c.

2587{
2588 int total_mod_loaded = 0;
2589 struct module_vector alpha_module_list;
2590
2592
2593 if (!alpha_module_list_create(&alpha_module_list)) {
2594 int idx;
2595
2596 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2597 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2598
2599 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
2600 cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
2601 }
2602 }
2603
2605 AST_VECTOR_FREE(&alpha_module_list);
2606
2607 return total_mod_loaded;
2608}
static int alpha_module_list_create(struct module_vector *alpha_module_list)
Definition: loader.c:2566
enum ast_module_support_level support_level
Definition: module.h:416
const char * description
Definition: module.h:352
#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 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 2638 of file loader.c.

2644{
2645 int conditions_met = 0;
2646 struct module_vector alpha_module_list;
2647
2649
2650 if (!alpha_module_list_create(&alpha_module_list)) {
2651 int idx;
2652
2653 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2654 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2655
2656 conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
2657 cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
2658 condition);
2659 }
2660 }
2661
2663 AST_VECTOR_FREE(&alpha_module_list);
2664
2665 return conditions_met;
2666}

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

2615{
2616 int total_mod_loaded = 0;
2617 struct module_vector alpha_module_list;
2618
2620
2621 if (!alpha_module_list_create(&alpha_module_list)) {
2622 int idx;
2623
2624 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2625 struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2626
2627 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
2628 cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
2629 }
2630 }
2631
2633 AST_VECTOR_FREE(&alpha_module_list);
2634
2635 return total_mod_loaded;
2636}

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

2545{
2546 /* Notify any module monitors that the use count for a
2547 resource has changed */
2548 struct loadupdate *m;
2549
2552 m->updater();
2554}

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(), ast_unload_resource(), ooh323_hangup(), ooh323_new(), ooh323c_call_thread(), start_resource(), and unistim_new().

◆ 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(), ast_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().

◆ inspect_module()

static unsigned int inspect_module ( const struct ast_module mod)
static

Definition at line 1656 of file loader.c.

1657{
1658 if (!mod->info->description) {
1659 module_load_error("Module '%s' does not provide a description.\n", mod->resource);
1660 return 1;
1661 }
1662
1663 if (!mod->info->key) {
1664 module_load_error("Module '%s' does not provide a license key.\n", mod->resource);
1665 return 1;
1666 }
1667
1668 if (verify_key((unsigned char *) mod->info->key)) {
1669 module_load_error("Module '%s' did not provide a valid license key.\n", mod->resource);
1670 return 1;
1671 }
1672
1673 if (!ast_strlen_zero(mod->info->buildopt_sum) &&
1674 strcmp(buildopt_sum, mod->info->buildopt_sum)) {
1675 module_load_error("Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
1676 module_load_error("Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
1677 return 1;
1678 }
1679
1680 return 0;
1681}
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:363
const char * key
Definition: module.h:359

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:316

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

2355{
2356 struct load_order_entry *order;
2357 unsigned int load_count;
2358 struct load_order load_order;
2359 int res = 0;
2360 int modulecount = 0;
2361 int i;
2362 struct ast_module *cur;
2363#ifdef AST_XML_DOCS
2364 struct ast_str *warning_msg;
2365 char deprecated_in[33];
2366 char removed_in[33];
2367 char replacement[129];
2368#endif
2369 struct timeval start_time = ast_tvnow();
2370 struct timeval end_time;
2371 int64_t usElapsed;
2372
2373 ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
2374
2375#if defined(HAVE_PERMANENT_DLOPEN)
2377 info_list_obj_cmp_fn); /* must not be cleaned at shutdown */
2378 if (!info_list) {
2379 fprintf(stderr, "Module info list allocation failure.\n");
2380 return 1;
2381 }
2382#endif
2383
2386
2389
2391 if (res) {
2392 goto done;
2393 }
2394
2396 if (res) {
2397 goto done;
2398 }
2399
2400 load_count = 0;
2402 load_count++;
2403
2404 if (load_count)
2405 ast_log(LOG_NOTICE, "%u modules will be loaded.\n", load_count);
2406
2407 res = load_resource_list(&load_order, &modulecount);
2408 if (res == -1) {
2409 ast_log(LOG_WARNING, "Some non-required modules failed to load.\n");
2410 res = 0;
2411 }
2412
2413done:
2415 ast_free(order->resource);
2416 ast_free(order);
2417 }
2418
2419#ifdef AST_XML_DOCS
2420 warning_msg = ast_str_create(512);
2421#endif
2422
2424#ifdef AST_XML_DOCS
2425 char *mod_name = NULL;
2426 struct ast_xml_xpath_results *results;
2427#endif
2428
2429 if (!cur->flags.running || cur->flags.declined) {
2430 continue;
2431 }
2432
2433#ifdef AST_XML_DOCS
2434 mod_name = get_name_from_resource(cur->resource);
2435 if (!warning_msg || !mod_name) {
2436 /* If we can't allocate memory, we have bigger issues */
2437 ast_free(mod_name);
2438 continue;
2439 }
2440
2441 /* Clear out the previous values */
2442 deprecated_in[0] = removed_in[0] = replacement[0] = 0;
2443
2444 results = ast_xmldoc_query("/docs/module[@name='%s']", mod_name);
2445 if (results) {
2446 struct ast_xml_node *deprecated_node, *removed_node, *replacement_node;
2447 struct ast_xml_node *metadata_nodes = ast_xml_node_get_children(ast_xml_xpath_get_first_result(results));
2448
2449 deprecated_node = ast_xml_find_element(metadata_nodes, "deprecated_in", NULL, NULL);
2450 if (deprecated_node) {
2451 const char *result_tmp = ast_xml_get_text(deprecated_node);
2452 if (!ast_strlen_zero(result_tmp)) {
2453 ast_copy_string(deprecated_in, result_tmp, sizeof(deprecated_in));
2454 }
2455 }
2456
2457 removed_node = ast_xml_find_element(metadata_nodes, "removed_in", NULL, NULL);
2458 if (removed_node) {
2459 const char *result_tmp = ast_xml_get_text(removed_node);
2460 if (!ast_strlen_zero(result_tmp)) {
2461 ast_copy_string(removed_in, result_tmp, sizeof(removed_in));
2462 }
2463 }
2464
2465 replacement_node = ast_xml_find_element(metadata_nodes, "replacement", NULL, NULL);
2466 if (replacement_node) {
2467 const char *result_tmp = ast_xml_get_text(replacement_node);
2468 if (!ast_strlen_zero(result_tmp)) {
2469 ast_copy_string(replacement, result_tmp, sizeof(replacement));
2470 }
2471 }
2472
2474 }
2475
2476 ast_str_reset(warning_msg);
2477
2478 if (cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED || !ast_strlen_zero(deprecated_in)
2479 || !ast_strlen_zero(removed_in) || !ast_strlen_zero(replacement)) {
2480 int already_butted = 0;
2481
2482 ast_str_append(&warning_msg, -1, "Module '%s' has been loaded", mod_name);
2483 if (!ast_strlen_zero(deprecated_in)) {
2484 ast_str_append(&warning_msg, -1, " but %s deprecated in Asterisk version %s",
2485 cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED ? "was" : "will be", deprecated_in);
2486 already_butted = 1;
2487 }
2488
2489 if (!ast_strlen_zero(removed_in)) {
2490 ast_str_append(&warning_msg, -1, " %s will be removed in Asterisk version %s", already_butted ? "and" : "but", removed_in);
2491 } else {
2492 ast_str_append(&warning_msg, -1, " %s may be removed in a future release", already_butted ? "and" : "but");
2493 }
2494
2495 ast_str_append(&warning_msg, -1, ".");
2496
2497 if (!ast_strlen_zero(replacement)) {
2498 ast_str_append(&warning_msg, -1, " Its replacement is '%s'.", replacement);
2499 }
2500 }
2501
2502 if (ast_str_strlen(warning_msg)) {
2503 ast_log(LOG_WARNING, "%s\n", ast_str_buffer(warning_msg));
2504 }
2505
2506 ast_free(mod_name);
2507#else
2509 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);
2510 }
2511#endif
2512 }
2513
2514#ifdef AST_XML_DOCS
2515 ast_free(warning_msg);
2516#endif
2517
2519
2520
2521 for (i = 0; i < AST_VECTOR_SIZE(&startup_errors); i++) {
2522 char *str = AST_VECTOR_GET(&startup_errors, i);
2523
2524 ast_log(LOG_ERROR, "%s", str);
2525 ast_free(str);
2526 }
2528
2531
2532 end_time = ast_tvnow();
2533 usElapsed = ast_tvdiff_us(end_time, start_time);
2534
2535#ifdef AST_XML_DOCS
2536 ast_debug(1, "Loader time with AST_XML_DOCS: %" PRId64 ".%06" PRId64 "\n", usElapsed / 1000000, usElapsed % 1000000);
2537#else
2538 ast_debug(1, "Loader time without AST_XML_DOCS: %" PRId64 ".%06" PRId64 "\n", usElapsed / 1000000, usElapsed % 1000000);
2539#endif
2540
2541 return res;
2542}
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define LOG_ERROR
#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:2117
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:2230
static int loader_builtin_init(struct load_order *load_order)
Definition: loader.c:2195
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:397
const char * ast_xml_get_text(struct ast_xml_node *node)
Get an element content string.
Definition: xml.c:355
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:417
void ast_xml_xpath_results_free(struct ast_xml_xpath_results *results)
Free the XPath results.
Definition: xml.c:427
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:299
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 1768 of file loader.c.

1770{
1771 struct ast_module *mod;
1773
1774 if ((mod = find_resource(resource_name, 0))) {
1775 if (mod->flags.running) {
1776 ast_log(LOG_WARNING, "Module '%s' already loaded and running.\n", resource_name);
1778 }
1779 } else {
1780 mod = load_dynamic_module(resource_name, suppress_logging);
1781 if (!mod) {
1783 }
1784
1785 if (module_post_register(mod)) {
1786 goto prestart_error;
1787 }
1788 }
1789
1790 mod->flags.required |= required;
1791 mod->flags.preload |= preload;
1792
1793 if (inspect_module(mod)) {
1794 goto prestart_error;
1795 }
1796
1797 mod->flags.declined = 0;
1798
1799 if (module_priorities) {
1800 if (AST_VECTOR_ADD_SORTED(module_priorities, mod, module_vector_cmp)) {
1801 goto prestart_error;
1802 }
1804 } else {
1805 res = start_resource(mod);
1806 }
1807
1809 publish_load_message(resource_name, res);
1810 }
1811
1812 return res;
1813
1814prestart_error:
1815 module_load_error("Module '%s' could not be loaded.\n", resource_name);
1819 publish_load_message(resource_name, res);
1820 }
1821 return res;
1822}
int ast_shutdown_final(void)
Definition: asterisk.c:1867
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:1656
static enum ast_module_load_result start_resource(struct ast_module *mod)
Definition: loader.c:1683
static void publish_load_message(const char *name, enum ast_module_load_result result)
Definition: loader.c:1536
@ 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 2117 of file loader.c.

2118{
2119 struct module_vector module_priorities;
2120 struct load_order_entry *order;
2121 int attempt = 0;
2122 int count = 0;
2123 int res = 0;
2124 int didwork;
2125 int lasttry = 0;
2126
2127 if (AST_VECTOR_INIT(&module_priorities, 500)) {
2128 ast_log(LOG_ERROR, "Failed to initialize module loader.\n");
2129
2130 return -1;
2131 }
2132
2133 while (res != -2) {
2134 didwork = 0;
2135
2137 enum ast_module_load_result lres;
2138
2139 /* Suppress log messages unless this is the last pass */
2140 lres = load_resource(order->resource, !lasttry, &module_priorities, order->required, order->preload);
2141 ast_debug(3, "PASS %d: %-46s %d\n", attempt, order->resource, lres);
2142 switch (lres) {
2145 /* We're supplying module_priorities so SUCCESS isn't possible but we
2146 * still have to test for it. SKIP is only used when we try to start a
2147 * module that is missing dependencies. */
2148 break;
2150 res = -1;
2151 break;
2153 /* LOAD_FAILURE only happens for required modules */
2154 if (lasttry) {
2155 /* This run is just to print errors. */
2156 module_load_error("*** Failed to load module %s - Required\n", order->resource);
2157 fprintf(stderr, "*** Failed to load module %s - Required\n", order->resource);
2158 res = -2;
2159 }
2160 break;
2162 /* load_resource worked and the module was added to module_priorities */
2164 ast_free(order->resource);
2165 ast_free(order);
2166 didwork = 1;
2167 break;
2168 }
2169 }
2171
2172 if (!didwork) {
2173 if (lasttry) {
2174 break;
2175 }
2176 /* We know the next try is going to fail, it's only being performed
2177 * so we can print errors. */
2178 lasttry = 1;
2179 }
2180 attempt++;
2181 }
2182
2183 if (res != -2) {
2184 res = start_resource_list(&module_priorities, &count);
2185 }
2186
2187 if (mod_count) {
2188 *mod_count += count;
2189 }
2190 AST_VECTOR_FREE(&module_priorities);
2191
2192 return res;
2193}
static int start_resource_list(struct module_vector *resources, int *mod_count)
Definition: loader.c:1985
@ 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 2195 of file loader.c.

2196{
2197 struct ast_module *mod;
2198
2199 /*
2200 * All built-in modules have registered the first time, now it's time to complete
2201 * the registration and add them to the priority list.
2202 */
2203 loader_ready = 1;
2204
2206 /* ast_module_register doesn't finish when first run by built-in modules. */
2208 }
2209
2210 /* Add all built-in modules to the load order. */
2212 if (!mod->flags.builtin) {
2213 continue;
2214 }
2215
2216 /* Parse dependendencies from mod->info. */
2217 if (module_post_register(mod)) {
2218 return -1;
2219 }
2220
2221 /* Built-in modules are not preloaded, most have an early load priority. */
2222 if (!add_to_load_order(mod->resource, load_order, 0, 0, 1)) {
2223 return -1;
2224 }
2225 }
2226
2227 return 0;
2228}
#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:1858
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 2230 of file loader.c.

2231{
2232 int res = -1;
2233 struct load_order_entry *order;
2234 struct ast_config *cfg;
2235 struct ast_variable *v;
2236 struct ast_flags config_flags = { 0 };
2237
2238 cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
2240 ast_log(LOG_WARNING, "'%s' invalid or missing.\n", AST_MODULE_CONFIG);
2241
2242 return -1;
2243 }
2244
2245 /* first, find all the modules we have been explicitly requested to load */
2246 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
2247 int required;
2248 int preload = 0;
2249
2250 if (!strncasecmp(v->name, "preload", strlen("preload"))) {
2251 preload = 1;
2252 if (!strcasecmp(v->name, "preload")) {
2253 required = 0;
2254 } else if (!strcasecmp(v->name, "preload-require")) {
2255 required = 1;
2256 } else {
2257 ast_log(LOG_ERROR, "Unknown configuration option '%s'", v->name);
2258 goto done;
2259 }
2260 } else if (!strcasecmp(v->name, "load")) {
2261 required = 0;
2262 } else if (!strcasecmp(v->name, "require")) {
2263 required = 1;
2264 } else if (!strcasecmp(v->name, "noload") || !strcasecmp(v->name, "autoload")) {
2265 continue;
2266 } else {
2267 ast_log(LOG_ERROR, "Unknown configuration option '%s'", v->name);
2268 goto done;
2269 }
2270
2271 if (required) {
2272 ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
2273 }
2274
2275 if (!add_to_load_order(v->value, load_order, required, preload, 0)) {
2276 goto done;
2277 }
2278 }
2279
2280 /* check if 'autoload' is on */
2281 if (ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
2282 /* if we are allowed to load dynamic modules, scan the directory for
2283 for all available modules and add them as well */
2284 DIR *dir = opendir(ast_config_AST_MODULE_DIR);
2285 struct dirent *dirent;
2286
2287 if (dir) {
2288 while ((dirent = readdir(dir))) {
2289 int ld = strlen(dirent->d_name);
2290
2291 /* Must end in .so to load it. */
2292
2293 if (ld < 4)
2294 continue;
2295
2296 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
2297 continue;
2298
2299 /* if there is already a module by this name in the module_list,
2300 skip this file */
2301 if (find_resource(dirent->d_name, 0))
2302 continue;
2303
2304 if (!add_to_load_order(dirent->d_name, load_order, 0, 0, 0)) {
2305 closedir(dir);
2306 goto done;
2307 }
2308 }
2309
2310 closedir(dir);
2311 } else {
2312 ast_log(LOG_ERROR, "Unable to open modules directory '%s'.\n", ast_config_AST_MODULE_DIR);
2313 goto done;
2314 }
2315 }
2316
2317 /* now scan the config for any modules we are prohibited from loading and
2318 remove them from the load order */
2319 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
2320 size_t baselen;
2321
2322 if (strcasecmp(v->name, "noload")) {
2323 continue;
2324 }
2325
2326 baselen = resource_name_baselen(v->value);
2328 if (!resource_name_match(v->value, baselen, order->resource)) {
2329 if (order->builtin) {
2330 ast_log(LOG_ERROR, "%s is a built-in module, you cannot specify 'noload'.\n", v->value);
2331 goto done;
2332 }
2333
2334 if (order->required) {
2335 ast_log(LOG_ERROR, "%s is configured with '%s' and 'noload', this is impossible.\n",
2336 v->value, order->preload ? "preload-require" : "require");
2337 goto done;
2338 }
2340 ast_free(order->resource);
2341 ast_free(order);
2342 }
2343 }
2345 }
2346
2347 res = 0;
2348done:
2349 ast_config_destroy(cfg);
2350
2351 return res;
2352}
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:3321
#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:783
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 1519 of file loader.c.

1520{
1521 int i;
1522 for (i = 0; i < ARRAY_LEN(load_results); i++) {
1523 if (load_results[i].result == result) {
1524 return load_results[i].name;
1525 }
1526 }
1527
1528 ast_log(LOG_WARNING, "Failed to find correct load result status. result %d\n", result);
1530}
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_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
#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:469
#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:2450
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 1361 of file loader.c.

1362{
1363 struct module_load_word word_l = {
1364 .word = word,
1365 .len = strlen(word),
1366 .moddir_len = strlen(ast_config_AST_MODULE_DIR),
1367 };
1368
1372}
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:1329
const char * word
Definition: loader.c:1324

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

1330{
1331 struct module_load_word *word = obj;
1332 struct ast_module *mod;
1333 char *filename_merged = NULL;
1334
1335 /* dir_name will never be shorter than word->moddir_len. */
1336 dir_name += word->moddir_len;
1337 if (!ast_strlen_zero(dir_name)) {
1338 ast_assert(dir_name[0] == '/');
1339
1340 dir_name += 1;
1341 if (ast_asprintf(&filename_merged, "%s/%s", dir_name, filename) < 0) {
1342 /* If we can't allocate the string just give up! */
1343 return -1;
1344 }
1345 filename = filename_merged;
1346 }
1347
1348 if (!strncasecmp(filename, word->word, word->len)) {
1349 /* Don't list files that are already loaded! */
1350 mod = find_resource(filename, 0);
1351 if (!mod || !mod->flags.running) {
1353 }
1354 }
1355
1356 ast_free(filename_merged);
1357
1358 return 0;
1359}
#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:2756

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

1300{
1301 switch (type) {
1303 return !mod->usecount && mod->flags.running && !mod->flags.declined;
1304
1306 return mod->flags.running && mod->info->reload;
1307
1309 return mod->flags.running;
1310
1312 /* if we have a 'struct ast_module' then we're loaded. */
1313 return 1;
1314 default:
1315 /* This function is not called for AST_MODULE_HELPER_LOAD. */
1316 /* Unknown ast_module_helper_type. Assume it doesn't match. */
1317 ast_assert(0);
1318
1319 return 0;
1320 }
1321}
@ 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:346

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:383
const char * enhances
Modules that we provide enhanced functionality for.
Definition: module.h:406
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:443

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:317
@ AST_MODPRI_DEFAULT
Definition: module.h:332
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 1536 of file loader.c.

1537{
1538 const char *status;
1539
1541
1543}
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:1480
static const char * loadresult2str(enum ast_module_load_result result)
Definition: loader.c:1519

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

1481{
1483 RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
1484 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1485 RAII_VAR(struct ast_json *, event_object, NULL, ast_json_unref);
1486
1487 ast_assert(type != NULL);
1490
1492 return;
1493 }
1494
1495 event_object = ast_json_pack("{s:s, s:s}",
1496 "Module", name,
1497 "Status", status);
1498 json_object = ast_json_pack("{s:s, s:i, s:o}",
1499 "type", type,
1500 "class_type", EVENT_FLAG_SYSTEM,
1501 "event", ast_json_ref(event_object));
1502 if (!json_object) {
1503 return;
1504 }
1505
1506 payload = ast_json_payload_create(json_object);
1507 if (!payload) {
1508 return;
1509 }
1510
1512 if (!message) {
1513 return;
1514 }
1515
1517}
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1872
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:1511
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 1559 of file loader.c.

1560{
1561 char res_buffer[8];
1562
1563 snprintf(res_buffer, sizeof(res_buffer), "%u", result);
1564 publish_load_message_type("Reload", S_OR(name, "All"), res_buffer);
1565}

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

1550{
1552}

References name, publish_load_message_type(), and status.

Referenced by ast_unload_resource().

◆ queue_reload_request()

static void queue_reload_request ( const char *  module)
static

Definition at line 1437 of file loader.c.

1438{
1439 struct reload_queue_item *item;
1440
1442
1443 if (do_full_reload) {
1445 return;
1446 }
1447
1448 if (ast_strlen_zero(module)) {
1449 /* A full reload request (when module is NULL) wipes out any previous
1450 reload requests and causes the queue to ignore future ones */
1452 ast_free(item);
1453 }
1454 do_full_reload = 1;
1455 } else {
1456 /* No reason to add the same module twice */
1458 if (!strcasecmp(item->module, module)) {
1460 return;
1461 }
1462 }
1463 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
1464 if (!item) {
1465 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
1467 return;
1468 }
1469 strcpy(item->module, module);
1471 }
1473}
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 1922 of file loader.c.

1924{
1925 struct module_vector missingdeps;
1926 struct ast_vector_const_string localdeps;
1927 int i = 0;
1928 int res = -1;
1929
1930 mod->flags.declined = 1;
1931 if (mod->flags.required) {
1932 module_load_error("Required module %s declined to load.\n", ast_module_name(mod));
1933
1934 return -2;
1935 }
1936
1937 module_load_error("%s declined to load.\n", ast_module_name(mod));
1938
1939 if (!*printmissing) {
1940 *printmissing = ast_str_create(64);
1941 if (!*printmissing) {
1942 return -1;
1943 }
1944 } else {
1945 ast_str_reset(*printmissing);
1946 }
1947
1948 AST_VECTOR_INIT(&missingdeps, 0);
1949 AST_VECTOR_INIT(&localdeps, 0);
1950
1951 /* Decline everything that depends on 'mod' from resources so we can
1952 * print a concise list. */
1953 while (res != -2 && i < AST_VECTOR_SIZE(resources)) {
1954 struct ast_module *dep = AST_VECTOR_GET(resources, i);
1955 i++;
1956
1958 if (dep->flags.declined || module_deps_missing_recursive(dep, &missingdeps)) {
1959 continue;
1960 }
1961
1962 if (AST_VECTOR_GET_CMP(&missingdeps, mod, AST_VECTOR_ELEM_DEFAULT_CMP)) {
1963 dep->flags.declined = 1;
1964 if (dep->flags.required) {
1965 module_load_error("Cannot load required module %s that depends on %s\n",
1966 ast_module_name(dep), ast_module_name(mod));
1967 res = -2;
1968 } else {
1969 AST_VECTOR_APPEND(&localdeps, ast_module_name(dep));
1970 }
1971 }
1972 }
1973 AST_VECTOR_FREE(&missingdeps);
1974
1975 if (res != -2 && AST_VECTOR_SIZE(&localdeps)) {
1976 AST_VECTOR_CALLBACK_VOID(&localdeps, STR_APPEND_TEXT, printmissing);
1977 module_load_error("Declined modules which depend on %s: %s\n",
1978 ast_module_name(mod), ast_str_buffer(*printmissing));
1979 }
1980 AST_VECTOR_FREE(&localdeps);
1981
1982 return res;
1983}
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:615
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 1683 of file loader.c.

1684{
1685 char tmp[256];
1686 enum ast_module_load_result res;
1687
1688 if (mod->flags.running) {
1690 }
1691
1692 if (!mod->info->load) {
1693 mod->flags.declined = 1;
1694
1696 }
1697
1698 if (module_deps_reference(mod, NULL)) {
1699 struct module_vector missing;
1700 int i;
1701
1702 AST_VECTOR_INIT(&missing, 0);
1703 if (module_deps_missing_recursive(mod, &missing)) {
1704 module_load_error("%s has one or more unknown dependencies.\n", mod->info->name);
1705 }
1706 for (i = 0; i < AST_VECTOR_SIZE(&missing); i++) {
1707 module_load_error("%s loaded before dependency %s!\n", mod->info->name,
1708 AST_VECTOR_GET(&missing, i)->info->name);
1709 }
1710 AST_VECTOR_FREE(&missing);
1711
1713 }
1714
1715 if (!ast_fully_booted) {
1716 ast_verb(4, "Loading %s.\n", mod->resource);
1717 }
1718 res = mod->info->load();
1719
1720 switch (res) {
1722 if (!ast_fully_booted) {
1723 ast_verb(5, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
1724 } else {
1725 ast_verb(4, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
1726 }
1727
1728 mod->flags.running = 1;
1729 if (mod->flags.builtin) {
1730 /* Built-in modules cannot be unloaded. */
1732 }
1733
1735 break;
1737 mod->flags.declined = 1;
1738 if (mod->flags.required) {
1740 }
1741 break;
1743 mod->flags.declined = 1;
1744 break;
1745 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
1747 break;
1748 }
1749
1750 /* Make sure the newly started module is at the end of the list */
1755
1756 return res;
1757}
#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:464
enum ast_module_load_result(* load)(void)
Definition: module.h:344
#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 1894 of file loader.c.

1895{
1896 enum ast_module_load_result lres;
1897
1898 /* Try to grab required references. */
1899 if (module_deps_reference(mod, NULL)) {
1900 /* We're likely to retry so not an error. */
1901 ast_debug(1, "Module %s is missing dependencies\n", mod->resource);
1902 return AST_MODULE_LOAD_SKIP;
1903 }
1904
1905 lres = start_resource(mod);
1906 ast_debug(3, "START: %-46s[%d] %d\n",
1907 mod->resource,
1909 lres);
1910
1911 if (lres == AST_MODULE_LOAD_SUCCESS) {
1912 (*count)++;
1913 } else if (lres == AST_MODULE_LOAD_FAILURE) {
1914 module_load_error("*** Failed to load %smodule %s\n",
1915 mod->flags.required ? "required " : "",
1916 mod->resource);
1917 }
1918
1919 return lres;
1920}
unsigned char load_pri
Definition: module.h:370

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

1986{
1987 struct module_vector missingdeps;
1988 int res = 0;
1989 struct ast_str *printmissing = NULL;
1990
1991 AST_VECTOR_INIT(&missingdeps, 0);
1992 while (res != -2 && AST_VECTOR_SIZE(resources)) {
1993 struct ast_module *mod = AST_VECTOR_REMOVE(resources, 0, 1);
1994 enum ast_module_load_result lres;
1995
1996 if (mod->flags.declined) {
1997 ast_debug(1, "%s is already declined, skipping\n", ast_module_name(mod));
1998 continue;
1999 }
2000
2001retry_load:
2002 lres = start_resource_attempt(mod, mod_count);
2003 if (lres == AST_MODULE_LOAD_SUCCESS) {
2004 /* No missing dependencies, successful. */
2005 continue;
2006 }
2007
2008 if (lres == AST_MODULE_LOAD_FAILURE) {
2009 res = -2;
2010 break;
2011 }
2012
2013 if (lres == AST_MODULE_LOAD_DECLINE) {
2014 res = resource_list_recursive_decline(resources, mod, &printmissing);
2015 continue;
2016 }
2017
2018 if (module_deps_missing_recursive(mod, &missingdeps)) {
2020 module_load_error("Failed to resolve dependencies for %s\n", ast_module_name(mod));
2021 res = resource_list_recursive_decline(resources, mod, &printmissing);
2022 continue;
2023 }
2024
2025 if (!AST_VECTOR_SIZE(&missingdeps)) {
2026 module_load_error("%s load function returned an invalid result. "
2027 "This is a bug in the module.\n", ast_module_name(mod));
2028 /* Dependencies were met but the module failed to start and the result
2029 * code was not AST_MODULE_LOAD_FAILURE or AST_MODULE_LOAD_DECLINE. */
2030 res = resource_list_recursive_decline(resources, mod, &printmissing);
2031 continue;
2032 }
2033
2034 ast_debug(1, "%s has %d dependencies\n",
2035 ast_module_name(mod), (int)AST_VECTOR_SIZE(&missingdeps));
2036 while (AST_VECTOR_SIZE(&missingdeps)) {
2037 int didwork = 0;
2038 int i = 0;
2039
2040 while (i < AST_VECTOR_SIZE(&missingdeps)) {
2041 struct ast_module *dep = AST_VECTOR_GET(&missingdeps, i);
2042
2043 if (dep->flags.declined) {
2044 ast_debug(1, "%s tried to start %s but it's already declined\n",
2045 ast_module_name(mod), ast_module_name(dep));
2046 i++;
2047 continue;
2048 }
2049
2050 ast_debug(1, "%s trying to start %s\n", ast_module_name(mod), ast_module_name(dep));
2051 lres = start_resource_attempt(dep, mod_count);
2052 if (lres == AST_MODULE_LOAD_SUCCESS) {
2053 ast_debug(1, "%s started %s\n", ast_module_name(mod), ast_module_name(dep));
2054 AST_VECTOR_REMOVE(&missingdeps, i, 1);
2057 didwork++;
2058 continue;
2059 }
2060
2061 if (lres == AST_MODULE_LOAD_FAILURE) {
2062 module_load_error("Failed to load %s.\n", ast_module_name(dep));
2063 res = -2;
2064 goto exitpoint;
2065 }
2066
2067 ast_debug(1, "%s failed to start %s\n", ast_module_name(mod), ast_module_name(dep));
2068 i++;
2069 }
2070
2071 if (!didwork) {
2072 break;
2073 }
2074 }
2075
2076 if (AST_VECTOR_SIZE(&missingdeps)) {
2077 if (!printmissing) {
2078 printmissing = ast_str_create(64);
2079 } else {
2080 ast_str_reset(printmissing);
2081 }
2082
2083 if (printmissing) {
2084 struct ast_vector_const_string localdeps;
2085
2086 AST_VECTOR_INIT(&localdeps, 0);
2087 module_deps_reference(mod, &localdeps);
2088 AST_VECTOR_CALLBACK_VOID(&localdeps, STR_APPEND_TEXT, &printmissing);
2089 AST_VECTOR_FREE(&localdeps);
2090 }
2091
2092 module_load_error("Failed to load %s due to dependencies: %s.\n",
2093 ast_module_name(mod),
2094 printmissing ? ast_str_buffer(printmissing) : "allocation failure creating list");
2095 res = resource_list_recursive_decline(resources, mod, &printmissing);
2096
2098
2099 continue;
2100 }
2101
2102 /* If we're here it means that we started with missingdeps and they're all loaded
2103 * now. It's impossible to reach this point a second time for the same module. */
2104 goto retry_load;
2105 }
2106
2107exitpoint:
2108 ast_free(printmissing);
2109 AST_VECTOR_FREE(&missingdeps);
2110
2111 return res;
2112}
static int resource_list_recursive_decline(struct module_vector *resources, struct ast_module *mod, struct ast_str **printmissing)
Definition: loader.c:1922
static enum ast_module_load_result start_resource_attempt(struct ast_module *mod, int *count)
Definition: loader.c:1894
#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 ast_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 2764 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