]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Avoid deadlock processing incoming AOC-E messages.
authorRichard Mudgett <rmudgett@digium.com>
Tue, 28 Sep 2010 01:04:37 +0000 (01:04 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Tue, 28 Sep 2010 01:04:37 +0000 (01:04 +0000)
Deadlock avoidance for the owner channel was not done when processing
incoming AOC-E messages.

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@289057 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/sig_pri.c

index 251e6a04a42afc411c02f0d8361ac1de704f7edd..9f3ebb7bee0088bff9c24404ceab468b70dceae7 100644 (file)
@@ -3256,20 +3256,29 @@ static void sig_pri_aoc_e_from_ast(struct sig_pri_chan *pvt, struct ast_aoc_deco
  * \brief send an AOC-E termination request on ast_channel and set
  * hangup delay.
  *
- * \param sig_pri_chan private
+ * \param pri sig_pri PRI control structure.
+ * \param chanpos Channel position in the span.
  * \param ms to delay hangup
  *
- * \note assumes pvt is locked
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
  *
  * \return Nothing
  */
-static void sig_pri_send_aoce_termination_request(struct sig_pri_chan *pvt, unsigned int ms)
+static void sig_pri_send_aoce_termination_request(struct sig_pri_span *pri, int chanpos, unsigned int ms)
 {
+       struct sig_pri_chan *pvt;
        struct ast_aoc_decoded *decoded = NULL;
        struct ast_aoc_encoded *encoded = NULL;
        size_t encoded_size;
        struct timeval whentohangup = { 0, };
 
+       sig_pri_lock_owner(pri, chanpos);
+       pvt = pri->pvts[chanpos];
+       if (!pvt->owner) {
+               return;
+       }
+
        if (!(decoded = ast_aoc_create(AST_AOC_REQUEST, 0, AST_AOC_REQUEST_E))) {
                ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
                goto cleanup_termination_request;
@@ -3296,6 +3305,7 @@ static void sig_pri_send_aoce_termination_request(struct sig_pri_chan *pvt, unsi
        ast_log(LOG_DEBUG, "Delaying hangup on %s for aoc-e msg\n", pvt->owner->name);
 
 cleanup_termination_request:
+       ast_channel_unlock(pvt->owner);
        ast_aoc_destroy_decoded(decoded);
        ast_aoc_destroy_encoded(encoded);
 }
@@ -5257,7 +5267,7 @@ static void *pri_dchannel(void *vpri)
                                                                        if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
                                                                                /* If a AOC-E msg was sent during the release, we must use a
                                                                                 * AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
-                                                                               ast_queue_control(pri->pvts[chanpos]->owner, AST_CONTROL_HANGUP);
+                                                                               pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
                                                                        } else {
                                                                                pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                                        }
@@ -5395,12 +5405,15 @@ static void *pri_dchannel(void *vpri)
 
                                                        if (do_hangup) {
 #if defined(HAVE_PRI_AOC_EVENTS)
-                                                               if (!pri->pvts[chanpos]->holding_aoce && pri->aoce_delayhangup && ast_bridged_channel(pri->pvts[chanpos]->owner)) {
-                                                                       sig_pri_send_aoce_termination_request(pri->pvts[chanpos], pri_get_timer(pri->pri, PRI_TIMER_T305) / 2);
+                                                               if (!pri->pvts[chanpos]->holding_aoce
+                                                                       && pri->aoce_delayhangup
+                                                                       && ast_bridged_channel(pri->pvts[chanpos]->owner)) {
+                                                                       sig_pri_send_aoce_termination_request(pri, chanpos,
+                                                                               pri_get_timer(pri->pri, PRI_TIMER_T305) / 2);
                                                                } else if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
                                                                        /* If a AOC-E msg was sent during the Disconnect, we must use a AST_CONTROL_HANGUP frame
                                                                         * to guarantee that frame gets read before hangup */
-                                                                       ast_queue_control(pri->pvts[chanpos]->owner, AST_CONTROL_HANGUP);
+                                                                       pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
                                                                } else {
                                                                        pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                                }