diff --git a/main/Makefile b/main/Makefile index c724e2012b0b18ba65d0ea0360a6c6bfdca0d460..b148b6f81e1128a5001c69d11203eafb7c69c015 100644 --- a/main/Makefile +++ b/main/Makefile @@ -17,6 +17,11 @@ all: asterisk include $(ASTTOPDIR)/Makefile.moddir_rules +# Can the MODSRC list be automated without needing built-in modules to be +# in a different directory? Would a different directory be better? +MOD_SRC:= +MOD_OBJS:=$(sort $(MOD_SRC:.c=.o)) + # Must include the extra ast_expr2.c, ast_expr2f.c, in case they need to be regenerated (because to force regeneration, we delete them) SRC:=$(wildcard *.c) ast_expr2.c ast_expr2f.c ifeq ($(AST_ASTERISKSSL),yes) @@ -25,7 +30,7 @@ endif ifeq ($(PJPROJECT_BUNDLED),yes) SRC:=$(filter-out libasteriskpj.c,$(SRC)) endif -OBJSFILTER=fskmodem_int.o fskmodem_float.o cygload.o buildinfo.o +OBJSFILTER:=$(MOD_OBJS) fskmodem_int.o fskmodem_float.o cygload.o buildinfo.o OBJS=$(filter-out $(OBJSFILTER),$(SRC:.c=.o)) # we need to link in the objects statically, not as a library, because @@ -178,6 +183,7 @@ GMIMELDFLAGS+=$(GMIME_LIB) endif $(OBJS): _ASTCFLAGS+=-DAST_MODULE=\"core\" -DAST_IN_CORE +$(MOD_OBJS): _ASTCFLAGS+=$(call MOD_ASTCFLAGS,$*) libasteriskssl.o: _ASTCFLAGS+=$(OPENSSL_INCLUDE) @@ -311,10 +317,10 @@ endif tcptls.o: _ASTCFLAGS+=$(OPENSSL_INCLUDE) -Wno-deprecated-declarations -$(MAIN_TGT): $(OBJS) $(ASTSSL_LIB) $(ASTPJ_LIB) $(LIBEDIT_OBJ) +$(MAIN_TGT): $(OBJS) $(MOD_OBJS) $(ASTSSL_LIB) $(ASTPJ_LIB) $(LIBEDIT_OBJ) @$(CC) -c -o buildinfo.o $(_ASTCFLAGS) buildinfo.c $(ASTCFLAGS) - $(ECHO_PREFIX) echo " [LD] $(OBJS) $(LIBEDIT_OBJ) -> $@" - $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(_ASTLDFLAGS) $(ASTLDFLAGS) $(OBJS) $(ASTSSL_LDLIBS) $(ASTPJ_LDLIBS) $(LIBEDIT_OBJ) buildinfo.o $(AST_LIBS) $(GMIMELDFLAGS) $(LIBEDIT_LIB) + $(ECHO_PREFIX) echo " [LD] $(OBJS) $(MOD_OBJS) $(LIBEDIT_OBJ) -> $@" + $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(_ASTLDFLAGS) $(ASTLDFLAGS) $(OBJS) $(MOD_OBJS) $(ASTSSL_LDLIBS) $(ASTPJ_LDLIBS) $(LIBEDIT_OBJ) buildinfo.o $(AST_LIBS) $(GMIMELDFLAGS) $(LIBEDIT_LIB) ifeq ($(GNU_LD),1) $(MAIN_TGT): asterisk.exports diff --git a/main/loader.c b/main/loader.c index ec8a184f5fc0196b1905494cbec641221fc19014..b8e8f940361bc1ad62691f27067339b6ae7a3393 100644 --- a/main/loader.c +++ b/main/loader.c @@ -112,6 +112,9 @@ static char buildopt_sum[33] = AST_BUILDOPT_SUM; AST_VECTOR(module_vector, struct ast_module *); +/* Built-in module registrations need special handling at startup */ +static unsigned int loader_ready; + /*! * \brief Internal flag to indicate all modules have been initially loaded. */ @@ -149,6 +152,8 @@ struct ast_module { unsigned int declined:1; /*! This module is being held open until it's time to shutdown. */ unsigned int keepuntilshutdown:1; + /*! The module is built-in. */ + unsigned int builtin:1; } flags; AST_DLLIST_ENTRY(ast_module) entry; char resource[0]; @@ -156,6 +161,13 @@ struct ast_module { static AST_DLLIST_HEAD_STATIC(module_list, ast_module); +/* + * module_list is cleared by its constructor possibly after + * we start accumulating built-in modules, so we need to + * use another list (without the lock) to accumulate them. + */ +static struct module_list builtin_module_list; + static int module_vector_strcasecmp(struct ast_module *a, struct ast_module *b) { return strcasecmp(a->resource, b->resource); @@ -445,6 +457,22 @@ void ast_module_register(const struct ast_module_info *info) { struct ast_module *mod; + if (!loader_ready) { + mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1); + if (!mod) { + /* We haven't even reached main() yet, if we can't + * allocate memory at this point just give up. */ + exit(2); + } + strcpy(mod->resource, info->name); /* safe */ + mod->info = info; + mod->flags.builtin = 1; + AST_DLLIST_INSERT_TAIL(&builtin_module_list, mod, entry); + + /* ast_module_register for built-in modules is run again during module preload. */ + return; + } + /* * This lock protects resource_being_loaded as well as the module * list. Normally we already have a lock on module_list when we @@ -1729,6 +1757,17 @@ int load_modules(unsigned int preload_only) AST_DLLIST_LOCK(&module_list); + /* + * All built-in modules have registered the first time, now it's time to complete + * the registration and add them to the priority list. + */ + loader_ready = 1; + + while ((resource_being_loaded = AST_DLLIST_REMOVE_HEAD(&builtin_module_list, entry))) { + /* ast_module_register doesn't finish when first run by built-in modules. */ + ast_module_register(resource_being_loaded->info); + } + cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags); if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);