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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">parking: Use channel snapshot instead of channel.<br><br>There exists a scenario where a thread can hold a lock on the<br>channels container while trying to lock a bridge. At the same<br>time another thread can hold the lock for said bridge while<br>attempting to retrieve a channel. This causes a deadlock.<br><br>This change fixes this scenario by retrieving a channel snapshot<br>instead of a channel, as information present in the snapshot<br>is all that is needed.<br><br>ASTERISK-28616<br><br>Change-Id: I68ceb1d62c7378addcd286e21be08a660a7cecf2<br>---<br>M res/parking/parking_bridge.c<br>1 file changed, 14 insertions(+), 15 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/res/parking/parking_bridge.c b/res/parking/parking_bridge.c</span><br><span>index e61486e..bfbe55f 100644</span><br><span>--- a/res/parking/parking_bridge.c</span><br><span>+++ b/res/parking/parking_bridge.c</span><br><span>@@ -72,9 +72,9 @@</span><br><span> }</span><br><span> </span><br><span> /* Only call this on a parked user that hasn't had its parker_dial_string set already */</span><br><span style="color: hsl(0, 100%, 40%);">-static int parked_user_set_parker_dial_string(struct parked_user *pu, struct ast_channel *parker)</span><br><span style="color: hsl(120, 100%, 40%);">+static int parked_user_set_parker_dial_string(struct parked_user *pu, const char *parker_channel_name)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  char *dial_string = ast_strdupa(ast_channel_name(parker));</span><br><span style="color: hsl(120, 100%, 40%);">+    char *dial_string = ast_strdupa(parker_channel_name);</span><br><span> </span><br><span>    ast_channel_name_to_dial_string(dial_string);</span><br><span>        pu->parker_dial_string = ast_strdup(dial_string);</span><br><span>@@ -93,7 +93,7 @@</span><br><span>  *</span><br><span>  * \param lot The parking lot we are assigning the user to</span><br><span>  * \param parkee The channel being parked</span><br><span style="color: hsl(0, 100%, 40%);">- * \param parker The channel performing the park operation (may be the same channel)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param parker_channel_name The name of the parker of this channel</span><br><span>  * \param parker_dial_string Takes priority over parker for setting the parker dial string if included</span><br><span>  * \param use_random_space if true, prioritize using a random parking space instead</span><br><span>  *        of ${PARKINGEXTEN} and/or automatic assignment from the parking lot</span><br><span>@@ -106,7 +106,7 @@</span><br><span>  *</span><br><span>  * \note ao2_cleanup this reference when you are done using it or you'll cause leaks.</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *chan, struct ast_channel *parker, const char *parker_dial_string, int use_random_space, int time_limit)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *chan, const char *parker_channel_name, const char *parker_dial_string, int use_random_space, int time_limit)</span><br><span> {</span><br><span>    struct parked_user *new_parked_user;</span><br><span>         int preferred_space = -1; /* Initialize to use parking lot defaults */</span><br><span>@@ -167,7 +167,7 @@</span><br><span>         if (parker_dial_string) {</span><br><span>            new_parked_user->parker_dial_string = ast_strdup(parker_dial_string);</span><br><span>     } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                if (!parker || parked_user_set_parker_dial_string(new_parked_user, parker)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (ast_strlen_zero(parker_channel_name) || parked_user_set_parker_dial_string(new_parked_user, parker_channel_name)) {</span><br><span>                      ao2_ref(new_parked_user, -1);</span><br><span>                        ao2_unlock(lot);</span><br><span>                     return NULL;</span><br><span>@@ -207,7 +207,8 @@</span><br><span> {</span><br><span>      struct parked_user *pu;</span><br><span>      const char *blind_transfer;</span><br><span style="color: hsl(0, 100%, 40%);">-     RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup); /* XXX replace with ast_channel_cleanup when available */</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_channel_snapshot *parker = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *parker_channel_name = NULL;</span><br><span>      RAII_VAR(struct park_common_datastore *, park_datastore, NULL, park_common_datastore_free);</span><br><span> </span><br><span>      ast_bridge_base_v_table.push(&self->base, bridge_channel, swap);</span><br><span>@@ -263,7 +264,7 @@</span><br><span>                /* There was either a failure to apply the datastore when performing park common setup or else we had alloc failures while cloning. Abort. */</span><br><span>                return -1;</span><br><span>   }</span><br><span style="color: hsl(0, 100%, 40%);">-       parker = ast_channel_get_by_name(park_datastore->parker_uuid);</span><br><span style="color: hsl(120, 100%, 40%);">+     parker = ast_channel_snapshot_get_latest(park_datastore->parker_uuid);</span><br><span> </span><br><span>        /* If the parker and the parkee are the same channel pointer, then the channel entered using</span><br><span>          * the park application. It's possible that the channel that transferred it is still alive (particularly</span><br><span>@@ -272,18 +273,16 @@</span><br><span>         blind_transfer = pbx_builtin_getvar_helper(bridge_channel->chan, "BLINDTRANSFER");</span><br><span>      blind_transfer = ast_strdupa(S_OR(blind_transfer, ""));</span><br><span>    ast_channel_unlock(bridge_channel->chan);</span><br><span style="color: hsl(0, 100%, 40%);">-    if ((!parker || parker == bridge_channel->chan)</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((!parker || !strcmp(parker->name, ast_channel_name(bridge_channel->chan)))</span><br><span>                 && !ast_strlen_zero(blind_transfer)) {</span><br><span style="color: hsl(0, 100%, 40%);">-          struct ast_channel *real_parker = ast_channel_get_by_name(blind_transfer);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-              if (real_parker) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      ao2_cleanup(parker);</span><br><span style="color: hsl(0, 100%, 40%);">-                    parker = real_parker;</span><br><span style="color: hsl(0, 100%, 40%);">-           }</span><br><span style="color: hsl(120, 100%, 40%);">+             parker_channel_name = blind_transfer;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              parker_channel_name = parker->name;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   pu = generate_parked_user(self->lot, bridge_channel->chan, parker,</span><br><span style="color: hsl(120, 100%, 40%);">+      pu = generate_parked_user(self->lot, bridge_channel->chan, parker_channel_name,</span><br><span>                park_datastore->parker_dial_string, park_datastore->randomize, park_datastore->time_limit);</span><br><span style="color: hsl(120, 100%, 40%);">+  ao2_cleanup(parker);</span><br><span>         if (!pu) {</span><br><span>           publish_parked_call_failure(bridge_channel->chan);</span><br><span>                return -1;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/13195">change 13195</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/+/13195"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: certified/16.3 </div>
<div style="display:none"> Gerrit-Change-Id: I68ceb1d62c7378addcd286e21be08a660a7cecf2 </div>
<div style="display:none"> Gerrit-Change-Number: 13195 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@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: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>