small cleanups to module.h and loader.c to start playing with
authorLuigi Rizzo <rizzo@icir.org>
Thu, 6 Apr 2006 09:10:31 +0000 (09:10 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Thu, 6 Apr 2006 09:10:31 +0000 (09:10 +0000)
new-style modules using static symbols.

Everything will still work as before, but new-style modules
can now be defined by putting a '#define STATIC_MODULE' somewhere
before including module.h, then declaring STATIC_MODULE the
various methods (load, unload, key...) that the module is
supposed to supply, and adding a 'STD_MOD(MOD_1, reload_fn, NULL, NULL)'
macro call at the end.
A module compiled in this way will be loaded RTLD_NOW|RTLD_LOCAL
so symbol pollution is reduced, and symbols are resolved immediately.
Removing just the '#define STATIC_MODULE' will restore the old
behaviour.

In order for a module to be loaded RTLD_NOW|RTLD_LOCAL, it must not
export any symbol[1], and all the modules it depends on (e.g. res_*)
must be loaded already.

[1] Mechanisms are in place, and will be enabled later, to still
allow such modules to 'export' symbols and resolving the dependencies
irrespective of the load order.

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

include/asterisk/module.h
loader.c

index b00ec48..5e1b6e0 100644 (file)
 extern "C" {
 #endif
 
-#ifndef STATIC_MODULE
-#define STATIC_MODULE  /* empty - symbols are global */
-#else
+#ifdef STATIC_MODULE   /* symbols are static */
+#define _HAVE_STATIC_MODULE
 #undef STATIC_MODULE
 #define STATIC_MODULE  static /* symbols are static */
-#endif
+#else  /* !STATIC_MODULE, symbols are global */
+#define STATIC_MODULE  /* empty - symbols are global */
 
 /*! \note Every module should provide these functions */
 /*! 
@@ -53,7 +53,7 @@ extern "C" {
  * If the module is not loaded successfully, Asterisk will call its
  * unload_module() function.
  */
-STATIC_MODULE int load_module(void);
+int load_module(void);
 
 /*! 
  * \brief Cleanup all module structures, sockets, etc.
@@ -64,7 +64,7 @@ STATIC_MODULE int load_module(void);
  *
  * \return Zero on success, or non-zero on error.
  */
-STATIC_MODULE int unload_module(void);
+int unload_module(void);
 
 /*! 
  * \brief Provides a usecount.
@@ -76,13 +76,13 @@ STATIC_MODULE int unload_module(void);
  *
  * \return The module's usecount.
  */
-STATIC_MODULE int usecount(void);                      /* How many channels provided by this module are in use? */
+int usecount(void);            /* How many channels provided by this module are in use? */
 
 /*! \brief Provides a description of the module.
  *
  * \return a short description of your module
  */
-STATIC_MODULE char *description(void);         /* Description of this module */
+char *description(void);               /* Description of this module */
 
 /*! 
  * \brief Returns the ASTERISK_GPL_KEY
@@ -99,7 +99,7 @@ STATIC_MODULE char *description(void);                /* Description of this module */
  *
  * \return ASTERISK_GPL_KEY
  */
-STATIC_MODULE char *key(void);         /* Return the below mentioned key, unmodified */
+char *key(void);               /* Return the below mentioned key, unmodified */
 
 /*! 
  * \brief Reload stuff.
@@ -109,7 +109,8 @@ STATIC_MODULE char *key(void);              /* Return the below mentioned key, unmodified */
  *
  * \return The return value is not used.
  */
-STATIC_MODULE int reload(void);                /* reload configs */
+int reload(void);              /* reload configs */
+#endif /* !STATIC_MODULE case */
 
 /*! \brief The text the key() function should return. */
 #define ASTERISK_GPL_KEY \
@@ -506,6 +507,15 @@ struct symbol_entry {
 #define        MOD_FIELD(f)    . ## f = f
 #define        METHOD_BASE(_base, _name)       . ## _name = _base ## _name
 
+/*
+ * Each 'registerable' entity has a pointer in the
+ * struct ast_registry, which points to an array of objects of
+ * the same type. The ast_*_register() function will be able to
+ * derive the size of these entries.
+ */
+struct ast_registry {
+       struct ast_cli_entry *clis;
+};
 
 struct module_symbols {
         int (*load_module)(void);
@@ -520,22 +530,27 @@ struct module_symbols {
                MOD_1,  /* old style, but symbols here */
                MOD_2,  /* new style, exported symbols */
        } type;
+       struct ast_registry *reg;
        struct symbol_entry *exported_symbols;
        struct symbol_entry *required_symbols;
 };
 
-#define STD_MOD(t, exp, req)                           \
+#ifndef _HAVE_STATIC_MODULE
+#define STD_MOD(t, reload_fn, exp, req)
+#else
+#define STD_MOD(t, reload_fn, exp, req)                        \
 struct module_symbols mod_data = {                     \
         .load_module = load_module,                    \
         .unload_module = unload_module,                        \
         .description = description,                    \
         .key = key,                                    \
-        .reload = reload,                              \
+        .reload = reload_fn,                           \
         .usecount = usecount,                          \
        .type = t,                                      \
        .exported_symbols = exp,                        \
        .required_symbols = req                         \
 };
+#endif /* _HAVE_STATIC_MODULE */
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }
index d467528..08dca97 100644 (file)
--- a/loader.c
+++ b/loader.c
@@ -683,26 +683,20 @@ static struct module * __load_resource(const char *resource_name,
        int res;
        struct module *cur;
        struct module_symbols *m, *m1;
-       int flags=RTLD_NOW;
+       int flags = RTLD_NOW;
        unsigned char *key;
        char tmp[80];
 
-       if (strncasecmp(resource_name, "res_", 4)) {
-#ifdef RTLD_GLOBAL
-               if (cfg) {
-                       char *val;
-                       if ((val = ast_variable_retrieve(cfg, "global", resource_name))
-                                       && ast_true(val))
-                               flags |= RTLD_GLOBAL;
-               }
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL    0       /* so it is a No-op */
 #endif
+       if (strncasecmp(resource_name, "res_", 4) && cfg) {
+               char *val = ast_variable_retrieve(cfg, "global", resource_name);
+               if (val && ast_true(val))
+                       flags |= RTLD_GLOBAL;
        } else {
                /* Resource modules are always loaded global and lazy */
-#ifdef RTLD_GLOBAL
                flags = (RTLD_GLOBAL | RTLD_LAZY);
-#else
-               flags = RTLD_LAZY;
-#endif
        }
        
        if (AST_LIST_LOCK(&module_list))
@@ -722,16 +716,19 @@ static struct module * __load_resource(const char *resource_name,
                ast_copy_string(fn, resource_name, sizeof(fn));
        else
                snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR, resource_name);
-#if 0
-       /* XXX test, open in a sane way */
+
+       /* open in a sane way */
        cur->lib = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
        if (cur->lib == NULL) {
-               ast_log(LOG_WARNING, "test %s\n", dlerror());
-       } else
+               ast_log(LOG_WARNING, "cannot load %s %s\n", fn, dlerror());
+       } else if ( (m1 = find_symbol(cur, "mod_data", 0)) == NULL || m1->type == MOD_0) {
+               /* old-style module, close and reload with standard flags */
                dlclose(cur->lib);
-#endif
+               cur->lib = NULL;
+       }
+       if (cur->lib == NULL)   /* try reopen with the old style */
+               cur->lib = dlopen(fn, flags);
 
-       cur->lib = dlopen(fn, flags);
        if (!cur->lib) {
                ast_log(LOG_WARNING, "%s\n", dlerror());
                free(cur);
@@ -740,10 +737,10 @@ static struct module * __load_resource(const char *resource_name,
        }
        m1 = find_symbol(cur, "mod_data", 0);
        if (m1 != NULL) {       /* new style module */
+               ast_log(LOG_WARNING, "new style %s (%d) loaded RTLD_LOCAL\n",
+                       resource_name, m1->type);
                errors = check_exported(cur);
                *m = *m1;
-               if (m->type == MOD_2)
-                       ast_log(LOG_WARNING, "new style %s, should unload and reload with RTLD_LOCAL\n", resource_name);
        } else {
                m->type = MOD_0;
                m->load_module = find_symbol(cur, "load_module", 1);