From: Terry Wilson Date: Wed, 13 Oct 2010 22:45:15 +0000 (+0000) Subject: Don't ignore frames that have been queued when softhangup'd X-Git-Tag: 1.4.38-rc1~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c2445e81b296bc4532892c8d8d9b63b8050c84f;p=thirdparty%2Fasterisk.git Don't ignore frames that have been queued when softhangup'd 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 --- diff --git a/main/channel.c b/main/channel.c index 65544af329..e6c716d40b 100644 --- a/main/channel.c +++ b/main/channel.c @@ -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