Merged revisions 88709 via svnmerge from
authorRussell Bryant <russell@russellbryant.com>
Mon, 5 Nov 2007 20:14:48 +0000 (20:14 +0000)
committerRussell Bryant <russell@russellbryant.com>
Mon, 5 Nov 2007 20:14:48 +0000 (20:14 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r88709 | russell | 2007-11-05 14:11:04 -0600 (Mon, 05 Nov 2007) | 20 lines

Merge the last bit of changes from asterisk/team/russell/readq-1.4

The issue here is that the channel frame readq handling got broken when the
code was converted to use the linked list macros.  It caused corruption of the
list head and tail pointers.  So, I fixed up the usage of the linked list
macros and in passing, simplified the code.  I also documented what the code
is doing, as it was a bit difficult to figure out at first.

This bug showed itself with crashes showing messed up head/tail pointers for
the readq.  However, there are a couple of crashes that aren't quite as obvious,
but I think may be related.  So, if your bug gets closed by this commit, but
you still have a problem, please reopen or create a new bug report.

(closes issue #10936)
(closes issue #10595)
(closes issue #10368)
(closes issue #11084)
(closes issue #10040)
(closes issue #10840)

........

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

main/channel.c

index d5fcb0a..d23c2b9 100644 (file)
@@ -3602,11 +3602,6 @@ int ast_do_masquerade(struct ast_channel *original)
        original->tech_pvt = clone->tech_pvt;
        clone->tech_pvt = t_pvt;
 
-       /* Swap the readq's */
-       cur = AST_LIST_FIRST(&original->readq);
-       AST_LIST_HEAD_SET_NOLOCK(&original->readq, AST_LIST_FIRST(&clone->readq));
-       AST_LIST_HEAD_SET_NOLOCK(&clone->readq, cur);
-
        /* Swap the alertpipes */
        for (i = 0; i < 2; i++) {
                x = original->alertpipe[i];
@@ -3614,6 +3609,33 @@ int ast_do_masquerade(struct ast_channel *original)
                clone->alertpipe[i] = x;
        }
 
+       /* 
+        * Swap the readq's.  The end result should be this:
+        *
+        *  1) All frames should be on the new (original) channel.
+        *  2) Any frames that were already on the new channel before this
+        *     masquerade need to be at the end of the readq, after all of the
+        *     frames on the old (clone) channel.
+        *  3) The alertpipe needs to get poked for every frame that was already
+        *     on the new channel, since we are now using the alert pipe from the
+        *     old (clone) channel.
+        */
+       {
+               AST_LIST_HEAD_NOLOCK(, ast_frame) tmp_readq;
+               AST_LIST_HEAD_SET_NOLOCK(&tmp_readq, NULL);
+
+               AST_LIST_APPEND_LIST(&tmp_readq, &original->readq, frame_list);
+               AST_LIST_APPEND_LIST(&original->readq, &clone->readq, frame_list);
+
+               while ((cur = AST_LIST_REMOVE_HEAD(&tmp_readq, frame_list))) {
+                       AST_LIST_INSERT_TAIL(&original->readq, cur, frame_list);
+                       if (original->alertpipe[1] > -1) {
+                               int poke = 0;
+                               write(original->alertpipe[1], &poke, sizeof(poke));
+                       }
+               }
+       }
+
        /* Swap the raw formats */
        x = original->rawreadformat;
        original->rawreadformat = clone->rawreadformat;
@@ -3622,27 +3644,8 @@ int ast_do_masquerade(struct ast_channel *original)
        original->rawwriteformat = clone->rawwriteformat;
        clone->rawwriteformat = x;
 
-       /* Save any pending frames on both sides.  Start by counting
-        * how many we're going to need... */
-       x = 0;
-       if (original->alertpipe[1] > -1) {
-               AST_LIST_TRAVERSE(&clone->readq, cur, frame_list)
-                       x++;
-       }
-
-       /* If we had any, prepend them to the ones already in the queue, and 
-        * load up the alertpipe */
-       if (AST_LIST_FIRST(&clone->readq)) {
-               AST_LIST_INSERT_TAIL(&clone->readq, AST_LIST_FIRST(&original->readq), frame_list);
-               AST_LIST_HEAD_SET_NOLOCK(&original->readq, AST_LIST_FIRST(&clone->readq));
-               AST_LIST_HEAD_SET_NOLOCK(&clone->readq, NULL);
-               for (i = 0; i < x; i++)
-                       write(original->alertpipe[1], &x, sizeof(x));
-       }
-       
        clone->_softhangup = AST_SOFTHANGUP_DEV;
 
-
        /* And of course, so does our current state.  Note we need not
           call ast_setstate since the event manager doesn't really consider
           these separate.  We do this early so that the clone has the proper