<p>George Joseph <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/13002">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  Benjamin Keith Ford: 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;">res_pjsip/res_pjsip_mwi: use centralized serializer pools<br><br>Both res_pjsip and res_pjsip_mwi made use of serializer pools. However, they<br>both implemented their own serializer pool functionality that was pretty much<br>identical in each of the source files. This patch removes the duplicated code,<br>and uses the new 'ast_serializer_pool' object instead.<br><br>Additionally res_pjsip_mwi enables a shutdown group on the pool since if the<br>timing was right the module could be unloaded while taskprocessor threads still<br>needed to execute, thus causing a crash.<br><br>Change-Id: I959b0805ad024585bbb6276593118be34fbf6e1d<br>---<br>M include/asterisk/res_pjsip.h<br>M res/res_pjsip.c<br>M res/res_pjsip_mwi.c<br>3 files changed, 64 insertions(+), 194 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index e295765..a78311d 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -2954,6 +2954,11 @@</span><br><span> long ast_sip_threadpool_queue_size(void);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Retrieve the SIP threadpool object</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_threadpool *ast_sip_threadpool(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \brief Retrieve transport state</span><br><span>  * \since 13.7.1</span><br><span>  *</span><br><span>diff --git a/res/res_pjsip.c b/res/res_pjsip.c</span><br><span>index 7123938..3e11a6b 100644</span><br><span>--- a/res/res_pjsip.c</span><br><span>+++ b/res/res_pjsip.c</span><br><span>@@ -34,6 +34,7 @@</span><br><span> #include "asterisk/utils.h"</span><br><span> #include "asterisk/astobj2.h"</span><br><span> #include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/serializer.h"</span><br><span> #include "asterisk/threadpool.h"</span><br><span> #include "asterisk/taskprocessor.h"</span><br><span> #include "asterisk/uuid.h"</span><br><span>@@ -2829,7 +2830,7 @@</span><br><span> #define SERIALIZER_POOL_SIZE                8</span><br><span> </span><br><span> /*! Pool of serializers to use if not supplied. */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_taskprocessor *serializer_pool[SERIALIZER_POOL_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_serializer_pool *sip_serializer_pool;</span><br><span> </span><br><span> static pjsip_endpoint *ast_pjsip_endpoint;</span><br><span> </span><br><span>@@ -4568,71 +4569,10 @@</span><br><span>  return ast_sip_create_serializer_group(name, NULL);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Shutdown the serializers in the default pool.</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 14.0.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \return Nothing</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static void serializer_pool_shutdown(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    int idx;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        for (idx = 0; idx < SERIALIZER_POOL_SIZE; ++idx) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_taskprocessor_unreference(serializer_pool[idx]);</span><br><span style="color: hsl(0, 100%, 40%);">-            serializer_pool[idx] = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Setup the serializers in the default pool.</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 14.0.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 on success.</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 on error.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int serializer_pool_setup(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];</span><br><span style="color: hsl(0, 100%, 40%);">-  int idx;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        for (idx = 0; idx < SERIALIZER_POOL_SIZE; ++idx) {</span><br><span style="color: hsl(0, 100%, 40%);">-           /* Create name with seq number appended. */</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/default");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-            serializer_pool[idx] = ast_sip_create_serializer(tps_name);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!serializer_pool[idx]) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    serializer_pool_shutdown();</span><br><span style="color: hsl(0, 100%, 40%);">-                     return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-       return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_taskprocessor *serializer_pool_pick(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  int idx;</span><br><span style="color: hsl(0, 100%, 40%);">-        int pos = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (!serializer_pool[0]) {</span><br><span style="color: hsl(0, 100%, 40%);">-              return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       for (idx = 1; idx < SERIALIZER_POOL_SIZE; ++idx) {</span><br><span style="color: hsl(0, 100%, 40%);">-           if (ast_taskprocessor_size(serializer_pool[idx]) < ast_taskprocessor_size(serializer_pool[pos])) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   pos = idx;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return serializer_pool[pos];</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> int ast_sip_push_task(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)</span><br><span> {</span><br><span>  if (!serializer) {</span><br><span style="color: hsl(0, 100%, 40%);">-              serializer = serializer_pool_pick();</span><br><span style="color: hsl(120, 100%, 40%);">+          serializer = ast_serializer_pool_get(sip_serializer_pool);</span><br><span>   }</span><br><span> </span><br><span>        return ast_taskprocessor_push(serializer, sip_task, task_data);</span><br><span>@@ -4713,7 +4653,7 @@</span><br><span> {</span><br><span>         if (!serializer) {</span><br><span>           /* Caller doesn't care which PJSIP serializer the task executes under. */</span><br><span style="color: hsl(0, 100%, 40%);">-           serializer = serializer_pool_pick();</span><br><span style="color: hsl(120, 100%, 40%);">+          serializer = ast_serializer_pool_get(sip_serializer_pool);</span><br><span>           if (!serializer) {</span><br><span>                   /* No serializer picked to execute the task */</span><br><span>                       return -1;</span><br><span>@@ -5071,6 +5011,11 @@</span><br><span>  return ast_threadpool_queue_size(sip_threadpool);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_threadpool *ast_sip_threadpool(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        return sip_threadpool;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef TEST_FRAMEWORK</span><br><span> AST_TEST_DEFINE(xml_sanitization_end_null)</span><br><span> {</span><br><span>@@ -5142,7 +5087,7 @@</span><br><span>       * These calls need the pjsip endpoint and serializer to clean up.</span><br><span>    * If they're not set, then there's nothing to clean up anyway.</span><br><span>       */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (ast_pjsip_endpoint && serializer_pool[0]) {</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ast_pjsip_endpoint && sip_serializer_pool) {</span><br><span>             ast_res_pjsip_cleanup_options_handling();</span><br><span>            ast_res_pjsip_cleanup_message_filter();</span><br><span>              ast_sip_destroy_distributor();</span><br><span>@@ -5278,7 +5223,9 @@</span><br><span>               goto error;</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (serializer_pool_setup()) {</span><br><span style="color: hsl(120, 100%, 40%);">+        sip_serializer_pool = ast_serializer_pool_create(</span><br><span style="color: hsl(120, 100%, 40%);">+             "pjsip/default", SERIALIZER_POOL_SIZE, sip_threadpool, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!sip_serializer_pool) {</span><br><span>          ast_log(LOG_ERROR, "Failed to create SIP serializer pool. Aborting load\n");</span><br><span>               goto error;</span><br><span>  }</span><br><span>@@ -5351,7 +5298,7 @@</span><br><span> </span><br><span>        /* These functions all check for NULLs and are safe to call at any time */</span><br><span>   ast_sip_destroy_scheduler();</span><br><span style="color: hsl(0, 100%, 40%);">-    serializer_pool_shutdown();</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_serializer_pool_destroy(sip_serializer_pool);</span><br><span>    ast_threadpool_shutdown(sip_threadpool);</span><br><span> </span><br><span>         return AST_MODULE_LOAD_DECLINE;</span><br><span>@@ -5382,7 +5329,7 @@</span><br><span>       */</span><br><span>  ast_sip_push_task_wait_servant(NULL, unload_pjsip, NULL);</span><br><span>    ast_sip_destroy_scheduler();</span><br><span style="color: hsl(0, 100%, 40%);">-    serializer_pool_shutdown();</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_serializer_pool_destroy(sip_serializer_pool);</span><br><span>    ast_threadpool_shutdown(sip_threadpool);</span><br><span> </span><br><span>         return 0;</span><br><span>diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c</span><br><span>index 82f6e46..bd25ea7 100644</span><br><span>--- a/res/res_pjsip_mwi.c</span><br><span>+++ b/res/res_pjsip_mwi.c</span><br><span>@@ -36,6 +36,7 @@</span><br><span> #include "asterisk/logger.h"</span><br><span> #include "asterisk/astobj2.h"</span><br><span> #include "asterisk/taskprocessor.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/serializer.h"</span><br><span> #include "asterisk/sorcery.h"</span><br><span> #include "asterisk/stasis.h"</span><br><span> #include "asterisk/mwi.h"</span><br><span>@@ -57,8 +58,11 @@</span><br><span> /*! Number of serializers in pool if one not supplied. */</span><br><span> #define MWI_SERIALIZER_POOL_SIZE 8</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Max timeout for all threads to join during an unload. */</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAX_UNLOAD_TIMEOUT_TIME 10 /* Seconds */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Pool of serializers to use if not supplied. */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_taskprocessor *mwi_serializer_pool[MWI_SERIALIZER_POOL_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_serializer_pool *mwi_serializer_pool;</span><br><span> </span><br><span> static void mwi_subscription_shutdown(struct ast_sip_subscription *sub);</span><br><span> static void mwi_to_ami(struct ast_sip_subscription *sub, struct ast_str **buf);</span><br><span>@@ -129,117 +133,6 @@</span><br><span>  char id[1];</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Shutdown the serializers in the mwi pool.</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 13.12.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \return Nothing</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static void mwi_serializer_pool_shutdown(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  int idx;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        for (idx = 0; idx < MWI_SERIALIZER_POOL_SIZE; ++idx) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_taskprocessor_unreference(mwi_serializer_pool[idx]);</span><br><span style="color: hsl(0, 100%, 40%);">-                mwi_serializer_pool[idx] = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Setup the serializers in the mwi pool.</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 13.12.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 on success.</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 on error.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int mwi_serializer_pool_setup(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];</span><br><span style="color: hsl(0, 100%, 40%);">-  int idx;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        for (idx = 0; idx < MWI_SERIALIZER_POOL_SIZE; ++idx) {</span><br><span style="color: hsl(0, 100%, 40%);">-               /* Create name with seq number appended. */</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/mwi");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                mwi_serializer_pool[idx] = ast_sip_create_serializer(tps_name);</span><br><span style="color: hsl(0, 100%, 40%);">-         if (!mwi_serializer_pool[idx]) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        mwi_serializer_pool_shutdown();</span><br><span style="color: hsl(0, 100%, 40%);">-                 return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-       return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Pick a mwi serializer from the pool.</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 13.12.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval least queue size task processor.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_taskprocessor *get_mwi_serializer(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      int idx;</span><br><span style="color: hsl(0, 100%, 40%);">-        int pos;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (!mwi_serializer_pool[0]) {</span><br><span style="color: hsl(0, 100%, 40%);">-          return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       for (pos = idx = 0; idx < MWI_SERIALIZER_POOL_SIZE; ++idx) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (ast_taskprocessor_size(mwi_serializer_pool[idx]) < ast_taskprocessor_size(mwi_serializer_pool[pos])) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   pos = idx;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return mwi_serializer_pool[pos];</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Set taskprocessor alert levels for the serializers in the mwi pool.</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 13.12.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 on success.</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 on error.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static int mwi_serializer_set_alert_levels(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     int idx;</span><br><span style="color: hsl(0, 100%, 40%);">-        long tps_queue_high;</span><br><span style="color: hsl(0, 100%, 40%);">-    long tps_queue_low;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!mwi_serializer_pool[0]) {</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       tps_queue_high = ast_sip_get_mwi_tps_queue_high();</span><br><span style="color: hsl(0, 100%, 40%);">-      if (tps_queue_high <= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_log(AST_LOG_WARNING, "Invalid taskprocessor high water alert trigger level '%ld'\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                      tps_queue_high);</span><br><span style="color: hsl(0, 100%, 40%);">-                tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       tps_queue_low = ast_sip_get_mwi_tps_queue_low();</span><br><span style="color: hsl(0, 100%, 40%);">-        if (tps_queue_low < -1 || tps_queue_high < tps_queue_low) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_log(AST_LOG_WARNING, "Invalid taskprocessor low water clear alert level '%ld'\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                 tps_queue_low);</span><br><span style="color: hsl(0, 100%, 40%);">-         tps_queue_low = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       for (idx = 0; idx < MWI_SERIALIZER_POOL_SIZE; ++idx) {</span><br><span style="color: hsl(0, 100%, 40%);">-               if (ast_taskprocessor_alert_set_levels(mwi_serializer_pool[idx], tps_queue_low, tps_queue_high)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      ast_log(AST_LOG_WARNING, "Failed to set alert levels for MWI serializer pool #%d.\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                         idx);</span><br><span style="color: hsl(0, 100%, 40%);">-           }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub,</span><br><span>             struct stasis_message *msg);</span><br><span> </span><br><span>@@ -1218,7 +1111,7 @@</span><br><span>     struct mwi_subscription *mwi_sub = obj;</span><br><span>      struct ast_taskprocessor *serializer = mwi_sub->is_solicited</span><br><span>              ? ast_sip_subscription_get_serializer(mwi_sub->sip_sub)</span><br><span style="color: hsl(0, 100%, 40%);">-              : get_mwi_serializer();</span><br><span style="color: hsl(120, 100%, 40%);">+               : ast_serializer_pool_get(mwi_serializer_pool);</span><br><span> </span><br><span>  if (ast_sip_push_task(serializer, serialized_notify, ao2_bump(mwi_sub))) {</span><br><span>           ao2_ref(mwi_sub, -1);</span><br><span>@@ -1233,7 +1126,8 @@</span><br><span>        struct mwi_subscription *mwi_sub = userdata;</span><br><span> </span><br><span>     if (stasis_subscription_final_message(sub, msg)) {</span><br><span style="color: hsl(0, 100%, 40%);">-              if (ast_sip_push_task(NULL, serialized_cleanup, ao2_bump(mwi_sub))) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (ast_sip_push_task(ast_serializer_pool_get(mwi_serializer_pool),</span><br><span style="color: hsl(120, 100%, 40%);">+                           serialized_cleanup, ao2_bump(mwi_sub))) {</span><br><span>                    ao2_ref(mwi_sub, -1);</span><br><span>                }</span><br><span>            return;</span><br><span>@@ -1396,7 +1290,8 @@</span><br><span>              return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (ast_sip_push_task(get_mwi_serializer(), serialized_notify, ao2_bump(mwi_sub))) {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ast_sip_push_task(ast_serializer_pool_get(mwi_serializer_pool),</span><br><span style="color: hsl(120, 100%, 40%);">+                   serialized_notify, ao2_bump(mwi_sub))) {</span><br><span>             ao2_ref(mwi_sub, -1);</span><br><span>        }</span><br><span> </span><br><span>@@ -1518,7 +1413,8 @@</span><br><span>                return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_sip_push_task(NULL, send_initial_notify_all, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_sip_push_task(ast_serializer_pool_get(mwi_serializer_pool),</span><br><span style="color: hsl(120, 100%, 40%);">+               send_initial_notify_all, NULL);</span><br><span> </span><br><span>  stasis_unsubscribe(sub);</span><br><span> }</span><br><span>@@ -1527,7 +1423,8 @@</span><br><span> {</span><br><span>   ast_free(default_voicemail_extension);</span><br><span>       default_voicemail_extension = ast_sip_get_default_voicemail_extension();</span><br><span style="color: hsl(0, 100%, 40%);">-        mwi_serializer_set_alert_levels();</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_serializer_pool_set_alerts(mwi_serializer_pool,</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_sip_get_mwi_tps_queue_high(), ast_sip_get_mwi_tps_queue_low());</span><br><span> }</span><br><span> </span><br><span> static struct ast_sorcery_observer global_observer = {</span><br><span>@@ -1548,14 +1445,16 @@</span><br><span>             return AST_MODULE_LOAD_DECLINE;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (mwi_serializer_pool_setup()) {</span><br><span style="color: hsl(120, 100%, 40%);">+    mwi_serializer_pool = ast_serializer_pool_create("pjsip/mwi",</span><br><span style="color: hsl(120, 100%, 40%);">+               MWI_SERIALIZER_POOL_SIZE, ast_sip_threadpool(), MAX_UNLOAD_TIMEOUT_TIME);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!mwi_serializer_pool) {</span><br><span>          ast_log(AST_LOG_WARNING, "Failed to create MWI serializer pool. The default SIP pool will be used for MWI\n");</span><br><span>     }</span><br><span> </span><br><span>        solicited_mwi = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MWI_BUCKETS,</span><br><span>           mwi_sub_hash, NULL, mwi_sub_cmp);</span><br><span>    if (!solicited_mwi) {</span><br><span style="color: hsl(0, 100%, 40%);">-           mwi_serializer_pool_shutdown();</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_serializer_pool_destroy(mwi_serializer_pool);</span><br><span>            ast_sip_unregister_subscription_handler(&mwi_handler);</span><br><span>           return AST_MODULE_LOAD_DECLINE;</span><br><span>      }</span><br><span>@@ -1563,7 +1462,7 @@</span><br><span>    unsolicited_mwi = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MWI_BUCKETS,</span><br><span>                 mwi_sub_hash, NULL, mwi_sub_cmp);</span><br><span>    if (!unsolicited_mwi) {</span><br><span style="color: hsl(0, 100%, 40%);">-         mwi_serializer_pool_shutdown();</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_serializer_pool_destroy(mwi_serializer_pool);</span><br><span>            ast_sip_unregister_subscription_handler(&mwi_handler);</span><br><span>           ao2_ref(solicited_mwi, -1);</span><br><span>          return AST_MODULE_LOAD_DECLINE;</span><br><span>@@ -1576,7 +1475,8 @@</span><br><span>      if (!ast_sip_get_mwi_disable_initial_unsolicited()) {</span><br><span>                create_mwi_subscriptions();</span><br><span>          if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_sip_push_task(NULL, send_initial_notify_all, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_sip_push_task(ast_serializer_pool_get(mwi_serializer_pool),</span><br><span style="color: hsl(120, 100%, 40%);">+                               send_initial_notify_all, NULL);</span><br><span>              } else {</span><br><span>                     struct stasis_subscription *sub;</span><br><span> </span><br><span>@@ -1586,6 +1486,15 @@</span><br><span>                }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mwi_serializer_pool) {</span><br><span style="color: hsl(120, 100%, 40%);">+           /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * If the mwi serializer pool was unable to be established then the module will</span><br><span style="color: hsl(120, 100%, 40%);">+                * use the default serializer pool. If this happens prevent manual unloading</span><br><span style="color: hsl(120, 100%, 40%);">+           * since there would now exist the potential for a crash on unload.</span><br><span style="color: hsl(120, 100%, 40%);">+            */</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_module_shutdown_ref(ast_module_info->self);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  return AST_MODULE_LOAD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span>@@ -1594,13 +1503,22 @@</span><br><span>   ast_sorcery_observer_remove(ast_sip_get_sorcery(), "global", &global_observer);</span><br><span>        ast_sorcery_observer_remove(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ao2_callback(unsolicited_mwi, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-       ao2_ref(unsolicited_mwi, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-   unsolicited_mwi = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (unsolicited_mwi) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ao2_callback(unsolicited_mwi, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+             ao2_ref(unsolicited_mwi, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+         unsolicited_mwi = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ao2_cleanup(solicited_mwi);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (solicited_mwi) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ao2_ref(solicited_mwi, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+           solicited_mwi = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   mwi_serializer_pool_shutdown();</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ast_serializer_pool_destroy(mwi_serializer_pool)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_WARNING, "Unload incomplete. Try again later\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%);">+     mwi_serializer_pool = NULL;</span><br><span> </span><br><span>      ast_sip_unregister_subscription_handler(&mwi_handler);</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/13002">change 13002</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/+/13002"/><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: I959b0805ad024585bbb6276593118be34fbf6e1d </div>
<div style="display:none"> Gerrit-Change-Number: 13002 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.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: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>