]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revision 291504 from
authorRichard Mudgett <rmudgett@digium.com>
Wed, 13 Oct 2010 19:01:48 +0000 (19:01 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Wed, 13 Oct 2010 19:01:48 +0000 (19:01 +0000)
https://origsvn.digium.com/svn/asterisk/be/branches/C.3-bier

..........
  r291504 | rmudgett | 2010-10-13 13:30:21 -0500 (Wed, 13 Oct 2010) | 11 lines

  Hold off ast_hangup() from destroying the ast_channel.

  Must get the ast_channel lock before proceeding with release_chan() and
  release_chan_early() to hold off ast_hangup() from destroying the
  ast_channel.

  Missed this change for -r291468.

  JIRA ABE-2598
  JIRA SWP-2317
..........

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

channels/chan_misdn.c

index 4a788483d5f5649f50a01450047ef302158e2e8f..a6d623e7a62b7fb1d964cba244768955ed6f3b2a 100644 (file)
@@ -8332,16 +8332,42 @@ static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
 {
        struct ast_channel *ast;
 
+       chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
+
        ast_mutex_lock(&release_lock);
+       for (;;) {
+               ast = ch->ast;
+               if (!ast || !ast_channel_trylock(ast)) {
+                       break;
+               }
+               DEADLOCK_AVOIDANCE(&release_lock);
+       }
        if (!cl_dequeue_chan(ch)) {
                /* Someone already released it. */
+               if (ast) {
+                       ast_channel_unlock(ast);
+               }
                ast_mutex_unlock(&release_lock);
                return;
        }
        ch->state = MISDN_CLEANING;
-       ast = ch->ast;
        ch->ast = NULL;
-       ast_mutex_unlock(&release_lock);
+       if (ast) {
+               MISDN_ASTERISK_TECH_PVT(ast) = NULL;
+               chan_misdn_log(1, bc->port,
+                       "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n",
+                       bc->pid,
+                       ast->context,
+                       ast->exten,
+                       S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
+                       S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""));
+
+               if (ast->_state != AST_STATE_RESERVED) {
+                       chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
+                       ast_setstate(ast, AST_STATE_DOWN);
+               }
+               ast_channel_unlock(ast);
+       }
 
 #if defined(AST_MISDN_ENHANCEMENTS)
        if (ch->peer) {
@@ -8355,8 +8381,6 @@ static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
                ch->dsp = NULL;
        }
 
-       chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
-
        /* releasing jitterbuffer */
        if (ch->jb) {
                misdn_jb_destroy(ch->jb);
@@ -8384,27 +8408,9 @@ static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
        close(ch->pipe[0]);
        close(ch->pipe[1]);
 
-       if (ast) {
-               ast_channel_lock(ast);
-               MISDN_ASTERISK_TECH_PVT(ast) = NULL;
-               chan_misdn_log(1, bc->port,
-                       "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n",
-                       bc->pid,
-                       ast->context,
-                       ast->exten,
-                       (ast->caller.id.name.valid && ast->caller.id.name.str)
-                               ? ast->caller.id.name.str : "",
-                       (ast->caller.id.number.valid && ast->caller.id.number.str)
-                               ? ast->caller.id.number.str : "");
-
-               if (ast->_state != AST_STATE_RESERVED) {
-                       chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
-                       ast_setstate(ast, AST_STATE_DOWN);
-               }
-               ast_channel_unlock(ast);
-       }
-
        ast_free(ch);
+
+       ast_mutex_unlock(&release_lock);
 }
 
 /*!
@@ -8422,15 +8428,30 @@ static void release_chan_early(struct chan_list *ch)
        struct ast_channel *ast;
 
        ast_mutex_lock(&release_lock);
+       for (;;) {
+               ast = ch->ast;
+               if (!ast || !ast_channel_trylock(ast)) {
+                       break;
+               }
+               DEADLOCK_AVOIDANCE(&release_lock);
+       }
        if (!cl_dequeue_chan(ch)) {
                /* Someone already released it. */
+               if (ast) {
+                       ast_channel_unlock(ast);
+               }
                ast_mutex_unlock(&release_lock);
                return;
        }
        ch->state = MISDN_CLEANING;
-       ast = ch->ast;
        ch->ast = NULL;
-       ast_mutex_unlock(&release_lock);
+       if (ast) {
+               MISDN_ASTERISK_TECH_PVT(ast) = NULL;
+               if (ast->_state != AST_STATE_RESERVED) {
+                       ast_setstate(ast, AST_STATE_DOWN);
+               }
+               ast_channel_unlock(ast);
+       }
 
 #if defined(AST_MISDN_ENHANCEMENTS)
        if (ch->peer) {
@@ -8469,16 +8490,9 @@ static void release_chan_early(struct chan_list *ch)
        close(ch->pipe[0]);
        close(ch->pipe[1]);
 
-       if (ast) {
-               ast_channel_lock(ast);
-               MISDN_ASTERISK_TECH_PVT(ast) = NULL;
-               if (ast->_state != AST_STATE_RESERVED) {
-                       ast_setstate(ast, AST_STATE_DOWN);
-               }
-               ast_channel_unlock(ast);
-       }
-
        ast_free(ch);
+
+       ast_mutex_unlock(&release_lock);
 }
 
 /*!