Merge "loader: support for permanent dlopen()"
This commit is contained in:
commit
3c106814d5
|
@ -702,6 +702,7 @@ PBX_DYNAMIC_LIST
|
|||
POW_LIB
|
||||
PBX_WORKING_FORK
|
||||
LIBOBJS
|
||||
PERMANENT_DLOPEN
|
||||
DISABLE_XMLDOC
|
||||
CONFIG_LIBXML2
|
||||
JANSSON_LIBS
|
||||
|
@ -1345,7 +1346,6 @@ infodir
|
|||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
|
@ -1454,6 +1454,7 @@ with_vpb
|
|||
with_x11
|
||||
with_z
|
||||
enable_xmldoc
|
||||
enable_permanent_dlopen
|
||||
enable_largefile
|
||||
enable_internal_poll
|
||||
enable_asteriskssl
|
||||
|
@ -1533,7 +1534,6 @@ datadir='${datarootdir}'
|
|||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
|
@ -1786,15 +1786,6 @@ do
|
|||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
|
@ -1932,7 +1923,7 @@ fi
|
|||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir runstatedir
|
||||
libdir localedir mandir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
|
@ -2085,7 +2076,6 @@ Fine tuning of the installation directories:
|
|||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
|
@ -2124,6 +2114,9 @@ Optional Features:
|
|||
--enable-dev-mode Turn on developer mode
|
||||
--enable-coverage Turn on code coverage tracking (for gcov)
|
||||
--disable-xmldoc Explicitly disable XML documentation
|
||||
--enable-permanent-dlopen
|
||||
Enable when your libc has a permanent dlopen like
|
||||
musl
|
||||
--disable-largefile omit support for large files
|
||||
--enable-internal-poll Use Asterisk's poll implementation
|
||||
--disable-asteriskssl Disable Asterisk's SSL wrapper library
|
||||
|
@ -14852,6 +14845,25 @@ fi
|
|||
|
||||
|
||||
|
||||
fi
|
||||
|
||||
# Check whether --enable-permanent-dlopen was given.
|
||||
if test "${enable_permanent_dlopen+set}" = set; then :
|
||||
enableval=$enable_permanent_dlopen; case "${enableval}" in
|
||||
y|ye|yes) PERMANENT_DLOPEN=yes ;;
|
||||
n|no) PERMANENT_DLOPEN=no ;;
|
||||
*) as_fn_error $? "bad value ${enableval} for --enable-permanent-dlopen" "$LINENO" 5 ;;
|
||||
esac
|
||||
else
|
||||
PERMANENT_DLOPEN=no
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test "${PERMANENT_DLOPEN}" == "yes"; then
|
||||
|
||||
$as_echo "#define HAVE_PERMANENT_DLOPEN 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
# some embedded systems omit internationalization (locale) support
|
||||
|
@ -14918,7 +14930,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -14964,7 +14976,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -14988,7 +15000,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -15033,7 +15045,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -15057,7 +15069,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -16357,8 +16369,6 @@ main ()
|
|||
if (*(data + i) != *(data3 + i))
|
||||
return 14;
|
||||
close (fd);
|
||||
free (data);
|
||||
free (data3);
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
|
|
14
configure.ac
14
configure.ac
|
@ -729,6 +729,20 @@ if test "${DISABLE_XMLDOC}" != "yes"; then
|
|||
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([permanent-dlopen],
|
||||
[AS_HELP_STRING([--enable-permanent-dlopen],
|
||||
[Enable when your libc has a permanent dlopen like musl])],
|
||||
[case "${enableval}" in
|
||||
y|ye|yes) PERMANENT_DLOPEN=yes ;;
|
||||
n|no) PERMANENT_DLOPEN=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-permanent-dlopen) ;;
|
||||
esac], [PERMANENT_DLOPEN=no])
|
||||
|
||||
AC_SUBST([PERMANENT_DLOPEN])
|
||||
if test "${PERMANENT_DLOPEN}" == "yes"; then
|
||||
AC_DEFINE([HAVE_PERMANENT_DLOPEN], 1, [Define to support libc with permanent dlopen.])
|
||||
fi
|
||||
|
||||
# some embedded systems omit internationalization (locale) support
|
||||
AC_CHECK_HEADERS([xlocale.h])
|
||||
|
||||
|
|
|
@ -603,6 +603,9 @@
|
|||
/* Define to 1 if your system defines the file flag O_SYMLINK in fcntl.h */
|
||||
#undef HAVE_O_SYMLINK
|
||||
|
||||
/* Define to support libc with permanent dlopen. */
|
||||
#undef HAVE_PERMANENT_DLOPEN
|
||||
|
||||
/* Define to indicate the PostgreSQL library */
|
||||
#undef HAVE_PGSQL
|
||||
|
||||
|
|
147
main/loader.c
147
main/loader.c
|
@ -153,6 +153,117 @@ static unsigned int loader_ready;
|
|||
static struct ast_vector_string startup_errors;
|
||||
static struct ast_str *startup_error_builder;
|
||||
|
||||
#if defined(HAVE_PERMANENT_DLOPEN)
|
||||
#define FIRST_DLOPEN 999
|
||||
|
||||
struct ao2_container *info_list = NULL;
|
||||
|
||||
struct info_list_obj {
|
||||
const struct ast_module_info *info;
|
||||
int dlopened;
|
||||
char name[0];
|
||||
};
|
||||
|
||||
static struct info_list_obj *info_list_obj_alloc(const char *name,
|
||||
const struct ast_module_info *info)
|
||||
{
|
||||
struct info_list_obj *new_entry;
|
||||
|
||||
new_entry = ao2_alloc(sizeof(*new_entry) + strlen(name) + 1, NULL);
|
||||
|
||||
if (!new_entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(new_entry->name, name); /* SAFE */
|
||||
new_entry->info = info;
|
||||
new_entry->dlopened = FIRST_DLOPEN;
|
||||
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
AO2_STRING_FIELD_CMP_FN(info_list_obj, name)
|
||||
|
||||
static char *get_name_from_resource(const char *resource)
|
||||
{
|
||||
int len;
|
||||
const char *last_three;
|
||||
char *mod_name;
|
||||
|
||||
if (!resource) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen(resource);
|
||||
if (len > 3) {
|
||||
last_three = &resource[len-3];
|
||||
if (!strcasecmp(last_three, ".so")) {
|
||||
mod_name = ast_calloc(1, len - 2);
|
||||
if (mod_name) {
|
||||
ast_copy_string(mod_name, resource, len - 2);
|
||||
return mod_name;
|
||||
} else {
|
||||
/* Unable to allocate memory. */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Resource is the name - happens when manually unloading a module. */
|
||||
mod_name = ast_calloc(1, len + 1);
|
||||
if (mod_name) {
|
||||
ast_copy_string(mod_name, resource, len + 1);
|
||||
return mod_name;
|
||||
}
|
||||
|
||||
/* Unable to allocate memory. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void manual_mod_reg(const void *lib, const char *resource)
|
||||
{
|
||||
struct info_list_obj *obj_tmp;
|
||||
char *mod_name;
|
||||
|
||||
if (lib) {
|
||||
mod_name = get_name_from_resource(resource);
|
||||
if (mod_name) {
|
||||
obj_tmp = ao2_find(info_list, mod_name, OBJ_SEARCH_KEY);
|
||||
if (obj_tmp) {
|
||||
if (obj_tmp->dlopened == FIRST_DLOPEN) {
|
||||
obj_tmp->dlopened = 1;
|
||||
} else {
|
||||
ast_module_register(obj_tmp->info);
|
||||
}
|
||||
ao2_ref(obj_tmp, -1);
|
||||
}
|
||||
ast_free(mod_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void manual_mod_unreg(const char *resource)
|
||||
{
|
||||
struct info_list_obj *obj_tmp;
|
||||
char *mod_name;
|
||||
|
||||
/* When Asterisk shuts down the destructor is called automatically. */
|
||||
if (ast_shutdown_final()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mod_name = get_name_from_resource(resource);
|
||||
if (mod_name) {
|
||||
obj_tmp = ao2_find(info_list, mod_name, OBJ_SEARCH_KEY);
|
||||
if (obj_tmp) {
|
||||
ast_module_unregister(obj_tmp->info);
|
||||
ao2_ref(obj_tmp, -1);
|
||||
}
|
||||
ast_free(mod_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static __attribute__((format(printf, 1, 2))) void module_load_error(const char *fmt, ...)
|
||||
{
|
||||
char *copy = NULL;
|
||||
|
@ -597,6 +708,23 @@ void ast_module_register(const struct ast_module_info *info)
|
|||
|
||||
/* give the module a copy of its own handle, for later use in registrations and the like */
|
||||
*((struct ast_module **) &(info->self)) = mod;
|
||||
|
||||
#if defined(HAVE_PERMANENT_DLOPEN)
|
||||
if (mod->flags.builtin != 1) {
|
||||
struct info_list_obj *obj_tmp = ao2_find(info_list, info->name,
|
||||
OBJ_SEARCH_KEY);
|
||||
|
||||
if (!obj_tmp) {
|
||||
obj_tmp = info_list_obj_alloc(info->name, info);
|
||||
if (obj_tmp) {
|
||||
ao2_link(info_list, obj_tmp);
|
||||
ao2_ref(obj_tmp, -1);
|
||||
}
|
||||
} else {
|
||||
ao2_ref(obj_tmp, -1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int module_post_register(struct ast_module *mod)
|
||||
|
@ -843,6 +971,10 @@ static void logged_dlclose(const char *name, void *lib)
|
|||
error = dlerror();
|
||||
ast_log(AST_LOG_ERROR, "Failure in dlclose for module '%s': %s\n",
|
||||
S_OR(name, "unknown"), S_OR(error, "Unknown error"));
|
||||
#if defined(HAVE_PERMANENT_DLOPEN)
|
||||
} else {
|
||||
manual_mod_unreg(name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -949,6 +1081,9 @@ static struct ast_module *load_dlopen(const char *resource_in, const char *so_ex
|
|||
|
||||
resource_being_loaded = mod;
|
||||
mod->lib = dlopen(filename, flags);
|
||||
#if defined(HAVE_PERMANENT_DLOPEN)
|
||||
manual_mod_reg(mod->lib, mod->resource);
|
||||
#endif
|
||||
if (resource_being_loaded) {
|
||||
struct ast_str *list;
|
||||
int c = 0;
|
||||
|
@ -968,6 +1103,9 @@ static struct ast_module *load_dlopen(const char *resource_in, const char *so_ex
|
|||
|
||||
resource_being_loaded = mod;
|
||||
mod->lib = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
|
||||
#if defined(HAVE_PERMANENT_DLOPEN)
|
||||
manual_mod_reg(mod->lib, mod->resource);
|
||||
#endif
|
||||
if (resource_being_loaded) {
|
||||
resource_being_loaded = NULL;
|
||||
|
||||
|
@ -2206,6 +2344,15 @@ int load_modules(void)
|
|||
|
||||
ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
|
||||
|
||||
#if defined(HAVE_PERMANENT_DLOPEN)
|
||||
info_list = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL,
|
||||
info_list_obj_cmp_fn); /* must not be cleaned at shutdown */
|
||||
if (!info_list) {
|
||||
fprintf(stderr, "Module info list allocation failure.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
AST_LIST_HEAD_INIT_NOLOCK(&load_order);
|
||||
AST_DLLIST_LOCK(&module_list);
|
||||
|
||||
|
|
Loading…
Reference in New Issue