<p>Ivan Poddubny has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/7540">View Change</a></p><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;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/40/7540/1</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 801695f..a140847 100644<br>--- a/apps/app_queue.c<br>+++ b/apps/app_queue.c<br>@@ -1575,6 +1575,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>@@ -2632,12 +2633,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>@@ -2664,6 +2674,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>@@ -11084,8 +11098,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>@@ -11242,8 +11254,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/7540">change 7540</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/7540"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I4956af2136ea2a7f110ac9272eae5f6e676d8f89 </div>
<div style="display:none"> Gerrit-Change-Number: 7540 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Ivan Poddubny <ivan.poddubny@gmail.com> </div>