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