<p>Friendly Automation <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11228">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Corey Farrell: Looks good to me, but someone else must approve
Joshua Colp: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved
Friendly Automation: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">loader: support for permanent dlopen()<br><br>Asterisk assumes that dlopen() will always run the constructor of a<br>shared library and every dlclose() will run its destructor. But dlopen()<br>may be permanent, meaning the constructor will only be run once, as is<br>the case with musl libc.<br><br>With a permanent dlopen() the Asterisk module loader does not work<br>correctly, because it's expectations regarding when the constructors and<br>destructors are run are not met. In fact a segmentation fault will occur<br>when the first module is "re-opened" that has AST_MODFLAG_GLOBAL_SYMBOLS<br>set (the dlopen() does not call the constructor, resource_being_loaded<br>is not set to NULL, then strlen is called with NULL instead of a string,<br>see issue ASTERISK-28319).<br><br>This commit adds code to the loader that will manually run the<br>constructors/destructors of the (non-builtin) modules where needed. To<br>achieve this a new ao2 container (linked list) is started and filled<br>with objects that contain the names of the modules and the pointers to<br>their respective info structs.<br><br>This behavior can be activated when configuring Asterisk<br>(--enable-permanent-dlopen). By default this is disabled, of course.<br><br>ASTERISK-28319 #close<br><br>Signed-off-by: Sebastian Kemper <sebastian_ml@gmx.net><br>Change-Id: I86693a0ecf25d5ba81c73773a03df4abc3426875<br>---<br>M configure<br>M configure.ac<br>M include/asterisk/autoconfig.h.in<br>M main/loader.c<br>4 files changed, 194 insertions(+), 20 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configure b/configure</span><br><span>index d8e1cbf..bb3244d 100755</span><br><span>--- a/configure</span><br><span>+++ b/configure</span><br><span>@@ -702,6 +702,7 @@</span><br><span> POW_LIB</span><br><span> PBX_WORKING_FORK</span><br><span> LIBOBJS</span><br><span style="color: hsl(120, 100%, 40%);">+PERMANENT_DLOPEN</span><br><span> DISABLE_XMLDOC</span><br><span> CONFIG_LIBXML2</span><br><span> JANSSON_LIBS</span><br><span>@@ -1337,7 +1338,6 @@</span><br><span> docdir</span><br><span> oldincludedir</span><br><span> includedir</span><br><span style="color: hsl(0, 100%, 40%);">-runstatedir</span><br><span> localstatedir</span><br><span> sharedstatedir</span><br><span> sysconfdir</span><br><span>@@ -1446,6 +1446,7 @@</span><br><span> with_x11</span><br><span> with_z</span><br><span> enable_xmldoc</span><br><span style="color: hsl(120, 100%, 40%);">+enable_permanent_dlopen</span><br><span> enable_largefile</span><br><span> enable_internal_poll</span><br><span> enable_asteriskssl</span><br><span>@@ -1525,7 +1526,6 @@</span><br><span> sysconfdir='${prefix}/etc'</span><br><span> sharedstatedir='${prefix}/com'</span><br><span> localstatedir='${prefix}/var'</span><br><span style="color: hsl(0, 100%, 40%);">-runstatedir='${localstatedir}/run'</span><br><span> includedir='${prefix}/include'</span><br><span> oldincludedir='/usr/include'</span><br><span> docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'</span><br><span>@@ -1778,15 +1778,6 @@</span><br><span> | -silent | --silent | --silen | --sile | --sil)</span><br><span> silent=yes ;;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- -runstatedir | --runstatedir | --runstatedi | --runstated \</span><br><span style="color: hsl(0, 100%, 40%);">- | --runstate | --runstat | --runsta | --runst | --runs \</span><br><span style="color: hsl(0, 100%, 40%);">- | --run | --ru | --r)</span><br><span style="color: hsl(0, 100%, 40%);">- ac_prev=runstatedir ;;</span><br><span style="color: hsl(0, 100%, 40%);">- -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \</span><br><span style="color: hsl(0, 100%, 40%);">- | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \</span><br><span style="color: hsl(0, 100%, 40%);">- | --run=* | --ru=* | --r=*)</span><br><span style="color: hsl(0, 100%, 40%);">- runstatedir=$ac_optarg ;;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)</span><br><span> ac_prev=sbindir ;;</span><br><span> -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \</span><br><span>@@ -1924,7 +1915,7 @@</span><br><span> for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \</span><br><span> datadir sysconfdir sharedstatedir localstatedir includedir \</span><br><span> oldincludedir docdir infodir htmldir dvidir pdfdir psdir \</span><br><span style="color: hsl(0, 100%, 40%);">- libdir localedir mandir runstatedir</span><br><span style="color: hsl(120, 100%, 40%);">+ libdir localedir mandir</span><br><span> do</span><br><span> eval ac_val=\$$ac_var</span><br><span> # Remove trailing slashes.</span><br><span>@@ -2077,7 +2068,6 @@</span><br><span> --sysconfdir=DIR read-only single-machine data [PREFIX/etc]</span><br><span> --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]</span><br><span> --localstatedir=DIR modifiable single-machine data [PREFIX/var]</span><br><span style="color: hsl(0, 100%, 40%);">- --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]</span><br><span> --libdir=DIR object code libraries [EPREFIX/lib]</span><br><span> --includedir=DIR C header files [PREFIX/include]</span><br><span> --oldincludedir=DIR C header files for non-gcc [/usr/include]</span><br><span>@@ -2116,6 +2106,9 @@</span><br><span> --enable-dev-mode Turn on developer mode</span><br><span> --enable-coverage Turn on code coverage tracking (for gcov)</span><br><span> --disable-xmldoc Explicitly disable XML documentation</span><br><span style="color: hsl(120, 100%, 40%);">+ --enable-permanent-dlopen</span><br><span style="color: hsl(120, 100%, 40%);">+ Enable when your libc has a permanent dlopen like</span><br><span style="color: hsl(120, 100%, 40%);">+ musl</span><br><span> --disable-largefile omit support for large files</span><br><span> --enable-internal-poll Use Asterisk's poll implementation</span><br><span> --disable-asteriskssl Disable Asterisk's SSL wrapper library</span><br><span>@@ -14816,6 +14809,25 @@</span><br><span> </span><br><span> fi</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+# Check whether --enable-permanent-dlopen was given.</span><br><span style="color: hsl(120, 100%, 40%);">+if test "${enable_permanent_dlopen+set}" = set; then :</span><br><span style="color: hsl(120, 100%, 40%);">+ enableval=$enable_permanent_dlopen; case "${enableval}" in</span><br><span style="color: hsl(120, 100%, 40%);">+ y|ye|yes) PERMANENT_DLOPEN=yes ;;</span><br><span style="color: hsl(120, 100%, 40%);">+ n|no) PERMANENT_DLOPEN=no ;;</span><br><span style="color: hsl(120, 100%, 40%);">+ *) as_fn_error $? "bad value ${enableval} for --enable-permanent-dlopen" "$LINENO" 5 ;;</span><br><span style="color: hsl(120, 100%, 40%);">+ esac</span><br><span style="color: hsl(120, 100%, 40%);">+else</span><br><span style="color: hsl(120, 100%, 40%);">+ PERMANENT_DLOPEN=no</span><br><span style="color: hsl(120, 100%, 40%);">+fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if test "${PERMANENT_DLOPEN}" == "yes"; then</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo "#define HAVE_PERMANENT_DLOPEN 1" >>confdefs.h</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # some embedded systems omit internationalization (locale) support</span><br><span> for ac_header in xlocale.h</span><br><span> do :</span><br><span>@@ -14880,7 +14892,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -14926,7 +14938,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -14950,7 +14962,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -14995,7 +15007,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -15019,7 +15031,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -16319,8 +16331,6 @@</span><br><span> if (*(data + i) != *(data3 + i))</span><br><span> return 14;</span><br><span> close (fd);</span><br><span style="color: hsl(0, 100%, 40%);">- free (data);</span><br><span style="color: hsl(0, 100%, 40%);">- free (data3);</span><br><span> return 0;</span><br><span> }</span><br><span> _ACEOF</span><br><span>diff --git a/configure.ac b/configure.ac</span><br><span>index 7acfcbc..3c64307 100644</span><br><span>--- a/configure.ac</span><br><span>+++ b/configure.ac</span><br><span>@@ -727,6 +727,20 @@</span><br><span> </span><br><span> fi</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+AC_ARG_ENABLE([permanent-dlopen],</span><br><span style="color: hsl(120, 100%, 40%);">+ [AS_HELP_STRING([--enable-permanent-dlopen],</span><br><span style="color: hsl(120, 100%, 40%);">+ [Enable when your libc has a permanent dlopen like musl])],</span><br><span style="color: hsl(120, 100%, 40%);">+ [case "${enableval}" in</span><br><span style="color: hsl(120, 100%, 40%);">+ y|ye|yes) PERMANENT_DLOPEN=yes ;;</span><br><span style="color: hsl(120, 100%, 40%);">+ n|no) PERMANENT_DLOPEN=no ;;</span><br><span style="color: hsl(120, 100%, 40%);">+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-permanent-dlopen) ;;</span><br><span style="color: hsl(120, 100%, 40%);">+ esac], [PERMANENT_DLOPEN=no])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AC_SUBST([PERMANENT_DLOPEN])</span><br><span style="color: hsl(120, 100%, 40%);">+if test "${PERMANENT_DLOPEN}" == "yes"; then</span><br><span style="color: hsl(120, 100%, 40%);">+ AC_DEFINE([HAVE_PERMANENT_DLOPEN], 1, [Define to support libc with permanent dlopen.])</span><br><span style="color: hsl(120, 100%, 40%);">+fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # some embedded systems omit internationalization (locale) support</span><br><span> AC_CHECK_HEADERS([xlocale.h])</span><br><span> </span><br><span>diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in</span><br><span>index 72f6ee0..9de15e5 100644</span><br><span>--- a/include/asterisk/autoconfig.h.in</span><br><span>+++ b/include/asterisk/autoconfig.h.in</span><br><span>@@ -603,6 +603,9 @@</span><br><span> /* Define to 1 if your system defines the file flag O_SYMLINK in fcntl.h */</span><br><span> #undef HAVE_O_SYMLINK</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Define to support libc with permanent dlopen. */</span><br><span style="color: hsl(120, 100%, 40%);">+#undef HAVE_PERMANENT_DLOPEN</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Define to indicate the PostgreSQL library */</span><br><span> #undef HAVE_PGSQL</span><br><span> </span><br><span>diff --git a/main/loader.c b/main/loader.c</span><br><span>index 3749c95..b46f745 100644</span><br><span>--- a/main/loader.c</span><br><span>+++ b/main/loader.c</span><br><span>@@ -153,6 +153,117 @@</span><br><span> static struct ast_vector_string startup_errors;</span><br><span> static struct ast_str *startup_error_builder;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(HAVE_PERMANENT_DLOPEN)</span><br><span style="color: hsl(120, 100%, 40%);">+#define FIRST_DLOPEN 999</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ao2_container *info_list = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct info_list_obj {</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_module_info *info;</span><br><span style="color: hsl(120, 100%, 40%);">+ int dlopened;</span><br><span style="color: hsl(120, 100%, 40%);">+ char name[0];</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct info_list_obj *info_list_obj_alloc(const char *name,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_module_info *info)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct info_list_obj *new_entry;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ new_entry = ao2_alloc(sizeof(*new_entry) + strlen(name) + 1, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!new_entry) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ strcpy(new_entry->name, name); /* SAFE */</span><br><span style="color: hsl(120, 100%, 40%);">+ new_entry->info = info;</span><br><span style="color: hsl(120, 100%, 40%);">+ new_entry->dlopened = FIRST_DLOPEN;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return new_entry;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AO2_STRING_FIELD_CMP_FN(info_list_obj, name)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static char *get_name_from_resource(const char *resource)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int len;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *last_three;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *mod_name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!resource) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ len = strlen(resource);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (len > 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+ last_three = &resource[len-3];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcasecmp(last_three, ".so")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ mod_name = ast_calloc(1, len - 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mod_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(mod_name, resource, len - 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ return mod_name;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Unable to allocate memory. */</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Resource is the name - happens when manually unloading a module. */</span><br><span style="color: hsl(120, 100%, 40%);">+ mod_name = ast_calloc(1, len + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mod_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(mod_name, resource, len + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ return mod_name;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Unable to allocate memory. */</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void manual_mod_reg(const void *lib, const char *resource)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct info_list_obj *obj_tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *mod_name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lib) {</span><br><span style="color: hsl(120, 100%, 40%);">+ mod_name = get_name_from_resource(resource);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mod_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ obj_tmp = ao2_find(info_list, mod_name, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (obj_tmp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (obj_tmp->dlopened == FIRST_DLOPEN) {</span><br><span style="color: hsl(120, 100%, 40%);">+ obj_tmp->dlopened = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_module_register(obj_tmp->info);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(obj_tmp, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(mod_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void manual_mod_unreg(const char *resource)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct info_list_obj *obj_tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *mod_name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* When Asterisk shuts down the destructor is called automatically. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_shutdown_final()) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mod_name = get_name_from_resource(resource);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mod_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ obj_tmp = ao2_find(info_list, mod_name, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (obj_tmp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_module_unregister(obj_tmp->info);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(obj_tmp, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(mod_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static __attribute__((format(printf, 1, 2))) void module_load_error(const char *fmt, ...)</span><br><span> {</span><br><span> char *copy = NULL;</span><br><span>@@ -597,6 +708,23 @@</span><br><span> </span><br><span> /* give the module a copy of its own handle, for later use in registrations and the like */</span><br><span> *((struct ast_module **) &(info->self)) = mod;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(HAVE_PERMANENT_DLOPEN)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mod->flags.builtin != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct info_list_obj *obj_tmp = ao2_find(info_list, info->name,</span><br><span style="color: hsl(120, 100%, 40%);">+ OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!obj_tmp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ obj_tmp = info_list_obj_alloc(info->name, info);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (obj_tmp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_link(info_list, obj_tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(obj_tmp, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(obj_tmp, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> }</span><br><span> </span><br><span> static int module_post_register(struct ast_module *mod)</span><br><span>@@ -843,6 +971,10 @@</span><br><span> error = dlerror();</span><br><span> ast_log(AST_LOG_ERROR, "Failure in dlclose for module '%s': %s\n",</span><br><span> S_OR(name, "unknown"), S_OR(error, "Unknown error"));</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(HAVE_PERMANENT_DLOPEN)</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ manual_mod_unreg(name);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>@@ -949,6 +1081,9 @@</span><br><span> </span><br><span> resource_being_loaded = mod;</span><br><span> mod->lib = dlopen(filename, flags);</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(HAVE_PERMANENT_DLOPEN)</span><br><span style="color: hsl(120, 100%, 40%);">+ manual_mod_reg(mod->lib, mod->resource);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> if (resource_being_loaded) {</span><br><span> struct ast_str *list;</span><br><span> int c = 0;</span><br><span>@@ -968,6 +1103,9 @@</span><br><span> </span><br><span> resource_being_loaded = mod;</span><br><span> mod->lib = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(HAVE_PERMANENT_DLOPEN)</span><br><span style="color: hsl(120, 100%, 40%);">+ manual_mod_reg(mod->lib, mod->resource);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> if (resource_being_loaded) {</span><br><span> resource_being_loaded = NULL;</span><br><span> </span><br><span>@@ -2206,6 +2344,15 @@</span><br><span> </span><br><span> ast_verb(1, "Asterisk Dynamic Loader Starting:\n");</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(HAVE_PERMANENT_DLOPEN)</span><br><span style="color: hsl(120, 100%, 40%);">+ info_list = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+ info_list_obj_cmp_fn); /* must not be cleaned at shutdown */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!info_list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "Module info list allocation failure.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> AST_LIST_HEAD_INIT_NOLOCK(&load_order);</span><br><span> AST_DLLIST_LOCK(&module_list);</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/11228">change 11228</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/11228"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: I86693a0ecf25d5ba81c73773a03df4abc3426875 </div>
<div style="display:none"> Gerrit-Change-Number: 11228 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Sebastian Kemper <sebastian_ml@gmx.net> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>