Merge "loader: support for permanent dlopen()"

This commit is contained in:
Friendly Automation 2019-04-19 09:06:03 -05:00 committed by Gerrit Code Review
commit 3c106814d5
4 changed files with 194 additions and 20 deletions

50
configure vendored
View File

@ -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

View File

@ -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])

View File

@ -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

View File

@ -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);