small cleanups to module.h and loader.c to start playing with

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
1.4
Luigi Rizzo 19 years ago
parent e57131511e
commit a60d8196df

@ -34,12 +34,12 @@
extern "C" { extern "C" {
#endif #endif
#ifndef STATIC_MODULE #ifdef STATIC_MODULE /* symbols are static */
#define STATIC_MODULE /* empty - symbols are global */ #define _HAVE_STATIC_MODULE
#else
#undef STATIC_MODULE #undef STATIC_MODULE
#define STATIC_MODULE static /* symbols are static */ #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 */ /*! \note Every module should provide these functions */
/*! /*!
@ -53,7 +53,7 @@ extern "C" {
* If the module is not loaded successfully, Asterisk will call its * If the module is not loaded successfully, Asterisk will call its
* unload_module() function. * unload_module() function.
*/ */
STATIC_MODULE int load_module(void); int load_module(void);
/*! /*!
* \brief Cleanup all module structures, sockets, etc. * \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. * \return Zero on success, or non-zero on error.
*/ */
STATIC_MODULE int unload_module(void); int unload_module(void);
/*! /*!
* \brief Provides a usecount. * \brief Provides a usecount.
@ -76,13 +76,13 @@ STATIC_MODULE int unload_module(void);
* *
* \return The module's usecount. * \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. /*! \brief Provides a description of the module.
* *
* \return a short description of your 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 * \brief Returns the ASTERISK_GPL_KEY
@ -99,7 +99,7 @@ STATIC_MODULE char *description(void); /* Description of this module */
* *
* \return ASTERISK_GPL_KEY * \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. * \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. * \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. */ /*! \brief The text the key() function should return. */
#define ASTERISK_GPL_KEY \ #define ASTERISK_GPL_KEY \
@ -506,6 +507,15 @@ struct symbol_entry {
#define MOD_FIELD(f) . ## f = f #define MOD_FIELD(f) . ## f = f
#define METHOD_BASE(_base, _name) . ## _name = _base ## _name #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 { struct module_symbols {
int (*load_module)(void); int (*load_module)(void);
@ -520,22 +530,27 @@ struct module_symbols {
MOD_1, /* old style, but symbols here */ MOD_1, /* old style, but symbols here */
MOD_2, /* new style, exported symbols */ MOD_2, /* new style, exported symbols */
} type; } type;
struct ast_registry *reg;
struct symbol_entry *exported_symbols; struct symbol_entry *exported_symbols;
struct symbol_entry *required_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 = { \ struct module_symbols mod_data = { \
.load_module = load_module, \ .load_module = load_module, \
.unload_module = unload_module, \ .unload_module = unload_module, \
.description = description, \ .description = description, \
.key = key, \ .key = key, \
.reload = reload, \ .reload = reload_fn, \
.usecount = usecount, \ .usecount = usecount, \
.type = t, \ .type = t, \
.exported_symbols = exp, \ .exported_symbols = exp, \
.required_symbols = req \ .required_symbols = req \
}; };
#endif /* _HAVE_STATIC_MODULE */
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)
} }

@ -683,26 +683,20 @@ static struct module * __load_resource(const char *resource_name,
int res; int res;
struct module *cur; struct module *cur;
struct module_symbols *m, *m1; struct module_symbols *m, *m1;
int flags=RTLD_NOW; int flags = RTLD_NOW;
unsigned char *key; unsigned char *key;
char tmp[80]; char tmp[80];
if (strncasecmp(resource_name, "res_", 4)) { #ifndef RTLD_GLOBAL
#ifdef RTLD_GLOBAL #define RTLD_GLOBAL 0 /* so it is a No-op */
if (cfg) {
char *val;
if ((val = ast_variable_retrieve(cfg, "global", resource_name))
&& ast_true(val))
flags |= RTLD_GLOBAL;
}
#endif #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 { } else {
/* Resource modules are always loaded global and lazy */ /* Resource modules are always loaded global and lazy */
#ifdef RTLD_GLOBAL
flags = (RTLD_GLOBAL | RTLD_LAZY); flags = (RTLD_GLOBAL | RTLD_LAZY);
#else
flags = RTLD_LAZY;
#endif
} }
if (AST_LIST_LOCK(&module_list)) 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)); ast_copy_string(fn, resource_name, sizeof(fn));
else else
snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR, resource_name); 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); cur->lib = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
if (cur->lib == NULL) { if (cur->lib == NULL) {
ast_log(LOG_WARNING, "test %s\n", dlerror()); ast_log(LOG_WARNING, "cannot load %s %s\n", fn, dlerror());
} else } 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); 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) { if (!cur->lib) {
ast_log(LOG_WARNING, "%s\n", dlerror()); ast_log(LOG_WARNING, "%s\n", dlerror());
free(cur); free(cur);
@ -740,10 +737,10 @@ static struct module * __load_resource(const char *resource_name,
} }
m1 = find_symbol(cur, "mod_data", 0); m1 = find_symbol(cur, "mod_data", 0);
if (m1 != NULL) { /* new style module */ 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); errors = check_exported(cur);
*m = *m1; *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 { } else {
m->type = MOD_0; m->type = MOD_0;
m->load_module = find_symbol(cur, "load_module", 1); m->load_module = find_symbol(cur, "load_module", 1);

Loading…
Cancel
Save