<p>George Joseph <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/7541">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved; Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_queue: Fix extension state subscriptions removed on dialplan reload<br><br>The approach with having a single global subscription to all extension<br>state changes has one issue: dynamically created hints don't have any<br>watchers and are therefore garbage collected on the first dialplan<br>reload.<br><br>This change creates a state subscription for every queue member with a<br>hint as state_interface, thus increasing the count of watches for<br>hints, so they are not destroyed prematurely anymore.<br><br>There are 2 side effects:<br>1. The state change callback in app_queue is not executed when<br>   there are no members referring to the extension.<br>2. The callback is called multiple times for the same hint if it's<br>   associated with more than one queue member.<br><br>Reported by: Steven T. Wheeler<br><br>ASTERISK-18411 #close<br><br>Change-Id: I4956af2136ea2a7f110ac9272eae5f6e676d8f89<br>---<br>M apps/app_queue.c<br>1 file changed, 15 insertions(+), 5 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/apps/app_queue.c b/apps/app_queue.c<br>index e3a4e22..6aea58c 100644<br>--- a/apps/app_queue.c<br>+++ b/apps/app_queue.c<br>@@ -1572,6 +1572,7 @@<br>   char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */<br>   char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */<br>     char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */<br>+        int state_id;                        /*!< Extension state callback id (if using hint) */<br>   char membername[80];                 /*!< Member name to use in queue logs */<br>      int penalty;                         /*!< Are we a last resort? */<br>         int calls;                           /*!< Number of calls serviced by this member */<br>@@ -2629,12 +2630,21 @@<br>      return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));<br> }<br> <br>+static void destroy_queue_member_cb(void *obj)<br>+{<br>+     struct member *mem = obj;<br>+<br>+ if (mem->state_id != -1) {<br>+                ast_extension_state_del(mem->state_id, extension_state_cb);<br>+       }<br>+}<br>+<br> /*! \brief allocate space for new queue member and set fields based on parameters passed */<br> static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)<br> {<br>    struct member *cur;<br> <br>-       if ((cur = ao2_alloc(sizeof(*cur), NULL))) {<br>+ if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) {<br>               cur->ringinuse = ringinuse;<br>                cur->penalty = penalty;<br>            cur->paused = paused;<br>@@ -2661,6 +2671,10 @@<br> <br>                   ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));<br>                     ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));<br>+<br>+                        cur->state_id = ast_extension_state_add(cur->state_context, cur->state_exten, extension_state_cb, NULL);<br>+            } else {<br>+                     cur->state_id = -1;<br>                }<br>             cur->status = get_queue_member_status(cur);<br>        }<br>@@ -11081,8 +11095,6 @@<br> <br>         device_state_sub = stasis_unsubscribe_and_join(device_state_sub);<br> <br>- ast_extension_state_del(0, extension_state_cb);<br>-<br>    ast_unload_realtime("queue_members");<br>       ao2_cleanup(queues);<br>  ao2_cleanup(pending_members);<br>@@ -11239,8 +11251,6 @@<br>        err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_complete_type);<br>   err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_dump_type);<br>       err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_ringnoanswer_type);<br>-<br>-   ast_extension_state_add(NULL, NULL, extension_state_cb, NULL);<br> <br>     if (err) {<br>            unload_module();<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7541">change 7541</a>. To unsubscribe, 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/7541"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I4956af2136ea2a7f110ac9272eae5f6e676d8f89 </div>
<div style="display:none"> Gerrit-Change-Number: 7541 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Ivan Poddubny <ivan.poddubny@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>