]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Don't ignore frames that have been queued when softhangup'd
authorTerry Wilson <twilson@digium.com>
Wed, 13 Oct 2010 22:45:15 +0000 (22:45 +0000)
committerTerry Wilson <twilson@digium.com>
Wed, 13 Oct 2010 22:45:15 +0000 (22:45 +0000)
When an outgoing call is answered and hung up by the far end *very* quickly, we
may not read any frames and therefor end up with a call that displays the wrong
disposition/DIALSTATUS. The reason is because ast_queue_hangup() immediately
sets the _softhangup flag on the channel and then queues the HANGUP control
frame, but __ast_read refuses to read any frames if ast_check_hangup() indicates
that a hangup request has been made (which it will if _softhangup is set). So,
we end up losing control frames.

This change makes __ast_read continue to read frames even if a soft hangup has
been requested. It queues a hangup frame to make sure that __ast_read() will
still eventually return NULL.

Much thanks to David Vossel for all of the reviews, discussion, and help!

(closes issue #16946)
Reported by: davidw

Review: https://reviewboard.asterisk.org/r/740/

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

main/channel.c

index 65544af3299728024b64432fcf33ef439ac14af6..e6c716d40bbe560e1dabac5ed88d9575f68d6d0a 100644 (file)
@@ -2186,7 +2186,18 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
        if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
                if (chan->generator)
                        ast_deactivate_generator(chan);
-               goto done;
+
+               /* It is possible for chan->_softhangup to be set, yet there still be control
+                * frames that still need to be read. Instead of just going to 'done' in the
+                * case of ast_check_hangup(), we instead need to send the HANGUP frame so that
+                * it can mark the end of the read queue. If there are frames to be read, 
+                * ast_queue_control will be called repeatedly, but will only queue one hangup
+                * frame. */
+               if (ast_check_hangup(chan)) {
+                       ast_queue_control(chan, AST_CONTROL_HANGUP);
+               } else {
+                       goto done;
+               }
        }
 
 #ifdef AST_DEVMODE