[asterisk-commits] rmudgett: branch 1.8 r313588 - in /branches/1.8: ./ main/channel.c res/res_agi.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Apr 13 11:31:59 CDT 2011
Author: rmudgett
Date: Wed Apr 13 11:31:50 2011
New Revision: 313588
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=313588
Log:
Merged revisions 313579 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.6.2
................
r313579 | rmudgett | 2011-04-13 11:29:49 -0500 (Wed, 13 Apr 2011) | 48 lines
Merged revisions 313545 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r313545 | rmudgett | 2011-04-13 11:21:24 -0500 (Wed, 13 Apr 2011) | 41 lines
Asterisk does not hangup a channel after endpoint hangs up.
If the call that the dialplan started an AGI script for is hungup while
the AGI script is in the middle of a command then the AGI script is not
notified of the hangup. There are many AGI Exec commands that this can
happen with. The reported applications have been: Background, Wait, Read,
and Dial. Also the AGI Get Data command.
* Don't wait on the Asterisk channel after it has hung up. The channel is
likely to never need servicing again.
* Restored the AGI script's ability to return the AGI_RESULT_HANGUP value
in run_agi(). It previously only could return AGI_RESULT_SUCCESS or
AGI_RESULT_FAILURE after the DeadAGI and AGI applications were merged.
(closes issue #17954)
Reported by: mn3250
Patches:
issue17954_v1.8.patch uploaded by rmudgett (license 664)
issue17954_v1.6.2.patch uploaded by rmudgett (license 664)
issue17954_v1.4.patch uploaded by rmudgett (license 664)
Tested by: rmudgett
JIRA SWP-2171
(closes issue #18492)
Reported by: devmod
Tested by: rmudgett
JIRA SWP-2761
(closes issue #18935)
Reported by: nvitaly
Tested by: astmiv, rmudgett
JIRA SWP-3216
(closes issue #17393)
Reported by: siby
Tested by: rmudgett
JIRA SWP-2727
Review: https://reviewboard.asterisk.org/r/1165/
........
................
Modified:
branches/1.8/ (props changed)
branches/1.8/main/channel.c
branches/1.8/res/res_agi.c
Propchange: branches/1.8/
------------------------------------------------------------------------------
Binary property 'branch-1.6.2-merged' - no diff available.
Modified: branches/1.8/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/main/channel.c?view=diff&rev=313588&r1=313587&r2=313588
==============================================================================
--- branches/1.8/main/channel.c (original)
+++ branches/1.8/main/channel.c Wed Apr 13 11:31:50 2011
@@ -3679,23 +3679,27 @@
} else {
goto done;
}
- }
-
+ } else {
#ifdef AST_DEVMODE
- /*
- * The ast_waitfor() code records which of the channel's file descriptors reported that
- * data is available. In theory, ast_read() should only be called after ast_waitfor()
- * reports that a channel has data available for reading. However, there still may be
- * some edge cases throughout the code where ast_read() is called improperly. This can
- * potentially cause problems, so if this is a developer build, make a lot of noise if
- * this happens so that it can be addressed.
- */
- if (chan->fdno == -1) {
- ast_log(LOG_ERROR,
- "ast_read() on chan '%s' called with no recorded file descriptor.\n",
- chan->name);
- }
+ /*
+ * The ast_waitfor() code records which of the channel's file
+ * descriptors reported that data is available. In theory,
+ * ast_read() should only be called after ast_waitfor() reports
+ * that a channel has data available for reading. However,
+ * there still may be some edge cases throughout the code where
+ * ast_read() is called improperly. This can potentially cause
+ * problems, so if this is a developer build, make a lot of
+ * noise if this happens so that it can be addressed.
+ *
+ * One of the potential problems is blocking on a dead channel.
+ */
+ if (chan->fdno == -1) {
+ ast_log(LOG_ERROR,
+ "ast_read() on chan '%s' called with no recorded file descriptor.\n",
+ chan->name);
+ }
#endif
+ }
prestate = chan->_state;
Modified: branches/1.8/res/res_agi.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/res/res_agi.c?view=diff&rev=313588&r1=313587&r2=313588
==============================================================================
--- branches/1.8/res/res_agi.c (original)
+++ branches/1.8/res/res_agi.c Wed Apr 13 11:31:50 2011
@@ -1178,7 +1178,7 @@
return 0;
}
-static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead);
+static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead);
static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[]);
static enum agi_result launch_asyncagi(struct ast_channel *chan, char *argv[], int *efd)
{
@@ -2180,12 +2180,14 @@
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
- return -1;
+ ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
+ return RESULT_FAILURE;
}
sildet = ast_dsp_new();
if (!sildet) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
- return -1;
+ ast_agi_send(agi->fd, chan, "200 result=-1\n");
+ return RESULT_FAILURE;
}
ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
}
@@ -3246,7 +3248,7 @@
return 0;
}
-static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
+static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
{
const char *argv[MAX_ARGS];
int argc = MAX_ARGS, res;
@@ -3297,9 +3299,10 @@
}
break;
case RESULT_FAILURE:
- /* They've already given the failure. We've been hung up on so handle this
- appropriately */
- return -1;
+ /* The RESULT_FAILURE code is usually because the channel hungup. */
+ return AGI_RESULT_FAILURE;
+ default:
+ break;
}
} else if ((c = find_command(argv, 0))) {
ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n");
@@ -3320,7 +3323,7 @@
"ResultCode: 510\r\n"
"Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd);
}
- return 0;
+ return AGI_RESULT_SUCCESS;
}
static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
{
@@ -3365,16 +3368,27 @@
}
}
ms = -1;
- c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
+ if (dead) {
+ c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
+ } else if (!ast_check_hangup(chan)) {
+ c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
+ } else {
+ /*
+ * Read the channel control queue until it is dry so we can
+ * switch to dead mode.
+ */
+ c = chan;
+ }
if (c) {
retry = AGI_NANDFS_RETRY;
/* Idle the channel until we get a command */
f = ast_read(c);
if (!f) {
ast_debug(1, "%s hungup\n", chan->name);
- returnstatus = AGI_RESULT_HANGUP;
needhup = 1;
- continue;
+ if (!returnstatus) {
+ returnstatus = AGI_RESULT_HANGUP;
+ }
} else {
/* If it's voice, write it to the audio pipe */
if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
@@ -3387,6 +3401,7 @@
} else if (outfd > -1) {
size_t len = sizeof(buf);
size_t buflen = 0;
+ enum agi_result cmd_status;
retry = AGI_NANDFS_RETRY;
buf[0] = '\0';
@@ -3409,9 +3424,6 @@
if (!buf[0]) {
/* Program terminated */
- if (returnstatus) {
- returnstatus = -1;
- }
ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", chan->name, request, returnstatus);
if (pid > 0)
waitpid(pid, status, 0);
@@ -3431,11 +3443,16 @@
buf[strlen(buf) - 1] = 0;
if (agidebug)
ast_verbose("<%s>AGI Rx << %s\n", chan->name, buf);
- returnstatus |= agi_handle_command(chan, agi, buf, dead);
- /* If the handle_command returns -1, we need to stop */
- if (returnstatus < 0) {
- needhup = 1;
- continue;
+ cmd_status = agi_handle_command(chan, agi, buf, dead);
+ switch (cmd_status) {
+ case AGI_RESULT_FAILURE:
+ if (dead || !ast_check_hangup(chan)) {
+ /* The failure was not because of a hangup. */
+ returnstatus = AGI_RESULT_FAILURE;
+ }
+ break;
+ default:
+ break;
}
} else {
if (--retry <= 0) {
More information about the asterisk-commits
mailing list