]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Set a module load priority for format modules.
authorRussell Bryant <russell@russellbryant.com>
Wed, 9 Dec 2009 15:14:21 +0000 (15:14 +0000)
committerRussell Bryant <russell@russellbryant.com>
Wed, 9 Dec 2009 15:14:21 +0000 (15:14 +0000)
A recent change to app_voicemail made it such that the module now assumes that
all format modules are available while processing voicemail configuration.
However, when autoloading modules, it was possible that app_voicemail was
loaded before the format modules. Since format modules don't depend on
anything, set a module load priority on them to ensure that they get loaded
first when autoloading.

This version of the patch is specific to Asterisk 1.4 and 1.6.0.  These versions
did not already support module load priority in the module API.  This adds a
trivial version of this which is just a module flag to include it in a pass before
loading "everything".

Thanks to mmichelson for the review!

(closes issue #16412)
Reported by: jiddings
Tested by: russell

Review: https://reviewboard.asterisk.org/r/445/

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@233782 65c4cc65-6c06-0410-ace0-fbb531ad65f3

16 files changed:
formats/format_g723.c
formats/format_g726.c
formats/format_g729.c
formats/format_gsm.c
formats/format_h263.c
formats/format_h264.c
formats/format_ilbc.c
formats/format_jpeg.c
formats/format_ogg_vorbis.c
formats/format_pcm.c
formats/format_sln.c
formats/format_vox.c
formats/format_wav.c
formats/format_wav_gsm.c
include/asterisk/module.h
main/loader.c

index dd5a1e6afa70ea0adf2d4dcc59b69070d4c87dd5..c394b0f1ec66635e9f05d2c9b701e8139630fae9 100644 (file)
@@ -160,4 +160,7 @@ static int unload_module(void)
        return ast_format_unregister(g723_1_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "G.723.1 Simple Timestamp File Format");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "G.723.1 Simple Timestamp File Format",
+       .load = load_module,
+       .unload = unload_module,
+);
index 499d545d259ea8345265125c60464c564e5f3900..fbb7e4791cacfe746163806cc19e08033bff3e0d 100644 (file)
@@ -274,4 +274,7 @@ static int unload_module(void)
        return(0);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw G.726 (16/24/32/40kbps) data");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw G.726 (16/24/32/40kbps) data",
+       .load = load_module,
+       .unload = unload_module,
+);
index 3f46bcbffa6173a23d1c6ae5627821c07260c216..a596c521c026e0f915a6c5bdf2495f2a65c5f026 100644 (file)
@@ -156,4 +156,7 @@ static int unload_module(void)
        return ast_format_unregister(g729_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw G729 data");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw G729 data",
+       .load = load_module,
+       .unload = unload_module,
+);
index 37fbd23826ba6a40de1a7596c5986a536bcd8ffe..9318fa3cf415a3a4241b121cff385d5d67140b89 100644 (file)
@@ -180,4 +180,7 @@ static int unload_module(void)
        return ast_format_unregister(gsm_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw GSM data");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw GSM data",
+       .load = load_module,
+       .unload = unload_module,
+);
index baa7a3efd804e643393eda55dd1040d14e8ea1ed..7cbcc8d4e261abf9591b4823c820cccf00e756b1 100644 (file)
@@ -194,4 +194,7 @@ static int unload_module(void)
        return ast_format_unregister(h263_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw H.263 data");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw H.263 data",
+       .load = load_module,
+       .unload = unload_module,
+);
index bc70a75c780e8a2ddff49f376e8702f9a8056da6..70b9dd948e2dc0b08e31395a09aecf324ba3188c 100644 (file)
@@ -183,4 +183,7 @@ static int unload_module(void)
        return ast_format_unregister(h264_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw H.264 data");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw H.264 data",
+       .load = load_module,
+       .unload = unload_module,
+);
index 659f42dbd37a2148fb2be07617f79adbd48279a4..906ca9264c09b6265a306a21036636289bc76a9e 100644 (file)
@@ -154,4 +154,7 @@ static int unload_module(void)
        return ast_format_unregister(ilbc_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw iLBC data");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw iLBC data",
+       .load = load_module,
+       .unload = unload_module,
+);
index edef171d2602b848bc50ad576b6082e1a6b0541e..64c197a99841c6295e06aaa7e3a5d0f91c084d7e 100644 (file)
@@ -124,4 +124,7 @@ static int unload_module(void)
        return 0;
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "JPEG (Joint Picture Experts Group) Image Format");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "JPEG (Joint Picture Experts Group) Image Format",
+       .load = load_module,
+       .unload = unload_module,
+);
index 7e20c00045f098ec299ed7cad60aca1a68a70d74..5a89098d627ff398da8c16776e5ccb80fe1cf734 100644 (file)
@@ -568,5 +568,8 @@ static int unload_module(void)
        return ast_format_unregister(vorbis_f.name);
 }
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "OGG/Vorbis audio");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "OGG/Vorbis audio",
+       .load = load_module,
+       .unload = unload_module,
+);
 
index a3deced7ae04f325d49b2139dd9e4ed012b91baf..a1292e11fed0696b6481733660a76b7a6fa72ecb 100644 (file)
@@ -504,4 +504,7 @@ static int unload_module(void)
                || ast_format_unregister(g722_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw/Sun uLaw/ALaw 8KHz (PCM,PCMA,AU), G.722 16Khz");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw/Sun uLaw/ALaw 8KHz (PCM,PCMA,AU), G.722 16Khz",
+       .load = load_module,
+       .unload = unload_module,
+);
index c8c5cc04bd9e00814fecd67a95a7f2bb19e024fa..d085b131b1aef2f2e30a35613333146ade574006 100644 (file)
@@ -138,4 +138,7 @@ static int unload_module(void)
        return ast_format_unregister(slin_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw Signed Linear Audio support (SLN)");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw Signed Linear Audio support (SLN)",
+       .load = load_module,
+       .unload = unload_module,
+);
index c729f3b5cbf5aaf1a83bc13f24bcbda420ac69c2..ef0697d33bd5b9dbe5595fa99bf6c26ba41a94d0 100644 (file)
@@ -143,4 +143,7 @@ static int unload_module(void)
        return ast_format_unregister(vox_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialogic VOX (ADPCM) File Format");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Dialogic VOX (ADPCM) File Format",
+       .load = load_module,
+       .unload = unload_module,
+);
index de92e881e7ba1c3681956933b12fef75532e679a..38c0fc7a8976bf3fb64713df0544ff1c3ce8ce2e 100644 (file)
@@ -528,4 +528,7 @@ static int unload_module(void)
        return ast_format_unregister(wav_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Microsoft WAV format (8000Hz Signed Linear)");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Microsoft WAV format (8000Hz Signed Linear)",
+       .load = load_module,
+       .unload = unload_module,
+);
index f82f9bc23e6af090e0457cd83a38fe426bcfba74..7e589bb88e45e43669834fd6e7cec244c29e81d2 100644 (file)
@@ -559,4 +559,7 @@ static int unload_module(void)
        return ast_format_unregister(wav49_f.name);
 }      
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Microsoft WAV format (Proprietary GSM)");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Microsoft WAV format (Proprietary GSM)",
+       .load = load_module,
+       .unload = unload_module,
+);
index 27eae4abe9bbb4cb0f733e0c7eb43092d0e7e5b0..7ea4e93a1eb4be7b7f305cf3cf8a2ffaafb4eb6f 100644 (file)
@@ -180,6 +180,14 @@ enum ast_module_flags {
        AST_MODFLAG_DEFAULT = 0,
        AST_MODFLAG_GLOBAL_SYMBOLS = (1 << 0),
        AST_MODFLAG_BUILDSUM = (1 << 1),
+       /*!
+        * \brief Load this module in the first pass on auto loading
+        *
+        * When module auto loading is used, modules with this flag set will
+        * be loaded after preloaded modules, but before all modules being
+        * automatically loaded without this flag set on them.
+        */
+       AST_MODFLAG_LOAD_FIRST = (1 << 2),
 };
 
 struct ast_module_info {
index 3fd424d48cb2d0cadbe6cbd29f605dda066cfd6e..9190c743b1dde1403a64fc452efae59215a42692 100644 (file)
@@ -117,6 +117,19 @@ static AST_LIST_HEAD_STATIC(reload_queue, reload_queue_item);
 */
 struct ast_module *resource_being_loaded;
 
+/*! \brief Load modules in this order. */
+enum module_load_pass {
+       /*! \brief AST_MODFLAG_LOAD_FIRST */
+       LOAD_FIRST,
+       /*! \brief AST_MODFLAG_GLOBAL_SYMBOLS */
+       LOAD_GLOBAL_SYMBOLS,
+       /*! \brief everything that is left */
+       LOAD_ALL,
+
+       /*! \brief Must remain at the end. */
+       LOAD_DONE,
+};
+
 /* XXX: should we check for duplicate resource names here? */
 
 void ast_module_register(const struct ast_module_info *info)
@@ -339,13 +352,13 @@ static void unload_dynamic_module(struct ast_module *mod)
                while (!dlclose(lib));
 }
 
-static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only)
+static struct ast_module *load_dynamic_module(const char *resource_in, enum module_load_pass load_pass)
 {
        char fn[256];
        void *lib;
        struct ast_module *mod;
        char *resource = (char *) resource_in;
-       unsigned int wants_global;
+       unsigned int wants_global = 0, not_yet = 0;
 
        if (strcasecmp(resource + strlen(resource) - 3, ".so")) {
                resource = alloca(strlen(resource_in) + 3);
@@ -386,11 +399,22 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned
                return NULL;
        }
 
-       wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
+       switch (load_pass) {
+       case LOAD_FIRST:
+               not_yet = !ast_test_flag(mod->info, AST_MODFLAG_LOAD_FIRST);
+               break;
+       case LOAD_GLOBAL_SYMBOLS:
+               wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
+               not_yet = !wants_global;
+               break;
+       case LOAD_ALL:
+               break;
+       case LOAD_DONE:
+               ast_log(LOG_ERROR, "Satan just bought a snowblower! (This should never happen, btw.)\n");
+               break;
+       }
 
-       /* if we are being asked only to load modules that provide global symbols,
-          and this one does not, then close it and return */
-       if (global_symbols_only && !wants_global) {
+       if (not_yet) {
                while (!dlclose(lib));
                return NULL;
        }
@@ -700,7 +724,7 @@ static unsigned int inspect_module(const struct ast_module *mod)
        return 0;
 }
 
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
+static enum ast_module_load_result load_resource(const char *resource_name, enum module_load_pass load_pass)
 {
        struct ast_module *mod;
        enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
@@ -711,13 +735,29 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
                        ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
                        return AST_MODULE_LOAD_DECLINE;
                }
-               if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
-                       return AST_MODULE_LOAD_SKIP;
+
+               switch (load_pass) {
+               case LOAD_FIRST:
+                       if (!ast_test_flag(mod->info, AST_MODFLAG_LOAD_FIRST)) {
+                               return AST_MODULE_LOAD_SKIP;
+                       }
+                       break;
+               case LOAD_GLOBAL_SYMBOLS:
+                       if (!ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
+                               return AST_MODULE_LOAD_SKIP;
+                       }
+                       break;
+               case LOAD_ALL:
+                       break;
+               case LOAD_DONE:
+                       ast_log(LOG_ERROR, "This should never happen, -EFLAMES!\n");
+                       break;
+               }
        } else {
 #ifdef LOADABLE_MODULES
-               if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
+               if (!(mod = load_dynamic_module(resource_name, load_pass))) {
                        /* don't generate a warning message during load_modules() */
-                       if (!global_symbols_only) {
+                       if (load_pass == LOAD_ALL) {
                                ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
                                return AST_MODULE_LOAD_DECLINE;
                        } else {
@@ -832,6 +872,7 @@ int load_modules(unsigned int preload_only)
        unsigned int load_count;
        struct load_order load_order;
        int res = 0;
+       int load_pass;
 
        int translate_status;
        char newname[18]; /* although this would normally be 80, max length in translate_module_name is 18 */
@@ -941,43 +982,28 @@ int load_modules(unsigned int preload_only)
        if (load_count)
                ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
 
-       /* first, load only modules that provide global symbols */
-       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
-               switch (load_resource(order->resource, 1)) {
-               case AST_MODULE_LOAD_SUCCESS:
-               case AST_MODULE_LOAD_DECLINE:
-                       AST_LIST_REMOVE_CURRENT(&load_order, entry);
-                       free(order->resource);
-                       free(order);
-                       break;
-               case AST_MODULE_LOAD_FAILURE:
-                       res = -1;
-                       goto done;
-               case AST_MODULE_LOAD_SKIP:
-                       /* try again later */
-                       break;
-               }
-       }
-       AST_LIST_TRAVERSE_SAFE_END;
-
-       /* now load everything else */
-       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
-               switch (load_resource(order->resource, 0)) {
-               case AST_MODULE_LOAD_SUCCESS:
-               case AST_MODULE_LOAD_DECLINE:
-                       AST_LIST_REMOVE_CURRENT(&load_order, entry);
-                       free(order->resource);
-                       free(order);
-                       break;
-               case AST_MODULE_LOAD_FAILURE:
-                       res = -1;
-                       goto done;
-               case AST_MODULE_LOAD_SKIP:
-                       /* should not happen */
-                       break;
+       for (load_pass = 0; load_pass < LOAD_DONE; load_pass++) {
+               AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
+                       switch (load_resource(order->resource, load_pass)) {
+                       case AST_MODULE_LOAD_SUCCESS:
+                       case AST_MODULE_LOAD_DECLINE:
+                               AST_LIST_REMOVE_CURRENT(&load_order, entry);
+                               free(order->resource);
+                               free(order);
+                               break;
+                       case AST_MODULE_LOAD_FAILURE:
+                               res = -1;
+                               goto done;
+                       case AST_MODULE_LOAD_SKIP:
+                               /* 
+                                * Try again later. This result is received when a module is
+                                * deferred because it is not a part of the current pass. 
+                                */
+                               break;
+                       }
                }
+               AST_LIST_TRAVERSE_SAFE_END;
        }
-       AST_LIST_TRAVERSE_SAFE_END;
 
 done:
        while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {