diff options
-rwxr-xr-x | configure | 72 | ||||
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | include/asterisk/autoconfig.h.in | 4 | ||||
-rw-r--r-- | main/loader.c | 30 |
4 files changed, 106 insertions, 9 deletions
@@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 40790 . +# From configure.ac Revision: 40837 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.60. # @@ -13654,6 +13654,76 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +{ echo "$as_me:$LINENO: checking checking for RTLD_NOLOAD" >&5 +echo $ECHO_N "checking checking for RTLD_NOLOAD... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <dlfcn.h> +int +main () +{ +int foo = RTLD_NOLOAD; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_RTLD_NOLOAD 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { echo "$as_me:$LINENO: checking checking for compiler 'attribute pure' support" >&5 echo $ECHO_N "checking checking for compiler 'attribute pure' support... $ECHO_C" >&6; } diff --git a/configure.ac b/configure.ac index 5bbb7107e..c3eacdc57 100644 --- a/configure.ac +++ b/configure.ac @@ -237,6 +237,15 @@ AC_LINK_IFELSE( AC_MSG_RESULT(no) ) +AC_MSG_CHECKING(checking for RTLD_NOLOAD) +AC_LINK_IFELSE( + AC_LANG_PROGRAM([#include <dlfcn.h>], + [int foo = RTLD_NOLOAD;]), + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_RTLD_NOLOAD], 1, [Define to 1 if your system has a dynamic linker that supports RTLD_NOLOAD.]), + AC_MSG_RESULT(no) +) + AST_GCC_ATTRIBUTE(pure) AST_GCC_ATTRIBUTE(malloc) AST_GCC_ATTRIBUTE(const) diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index 2f12438a6..94236ae96 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -270,6 +270,10 @@ /* Define to 1 if you have the `rint' function. */ #undef HAVE_RINT +/* Define to 1 if your system has a dynamic linker that supports RTLD_NOLOAD. + */ +#undef HAVE_RTLD_NOLOAD + /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT diff --git a/main/loader.c b/main/loader.c index 4d8e527f3..a4cf7a825 100644 --- a/main/loader.c +++ b/main/loader.c @@ -324,7 +324,7 @@ static struct ast_module *find_resource(const char *resource, int do_lock) static void unload_dynamic_module(struct ast_module *mod) { if (mod->lib) - dlclose(mod->lib); + while (!dlclose(mod->lib)); /* WARNING: the structure pointed to by mod is now gone! */ } @@ -368,7 +368,7 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned */ if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) { /* no, it did not, so close it and return */ - dlclose(lib); + while (!dlclose(lib)); /* note that the module's destructor will call ast_module_unregister(), which will free the structure we allocated in resource_being_loaded */ return NULL; @@ -376,15 +376,27 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS); - /* we are done with this first load, so clean up and start over */ - - dlclose(lib); - resource_being_loaded = NULL; - /* 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 (global_symbols_only && !wants_global) { + while (!dlclose(lib)); + return NULL; + } + + /* if the system supports RTLD_NOLOAD, we can just 'promote' the flags + on the already-opened library to what we want... if not, we have to + close it and start over + */ +#if HAVE_RTLD_NOLOAD + if (!dlopen(fn, RTLD_NOLOAD | (wants_global ? RTLD_GLOBAL : RTLD_NOW))) { + ast_log(LOG_WARNING, "%s\n", dlerror()); + while (!dlclose(lib)); + free(resource_being_loaded); return NULL; + } +#else + while (!dlclose(lib)); + resource_being_loaded = NULL; /* start the load process again */ @@ -402,6 +414,8 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned /* since the module was successfully opened, and it registered itself the previous time we did that, we're going to assume it worked this time too :) */ +#endif + AST_LIST_LAST(&module_list)->lib = lib; resource_being_loaded = NULL; |