aboutsummaryrefslogtreecommitdiffstats
path: root/res
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-11 15:26:51 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-11 15:26:51 +0000
commit6f23eea0dc09e316a628accf403cf1de3f59c227 (patch)
tree162da55aa831f0f60e0f321be9d68b71642ce486 /res
parent980a442aec2d479c2fc10a664612b40ad0ce1077 (diff)
(closes issue #10553)
Reported by: juggie Patches: res_agi_fgets-2.patch uploaded by juggie (license 24) Tested by: juggie When using fastagi, fgets() can return before a full line is read. Add explicit handling for the case where it gets interrupted. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@82245 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res')
-rw-r--r--res/res_agi.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/res/res_agi.c b/res/res_agi.c
index c442768aa..cae43e667 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -67,6 +67,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define MAX_ARGS 128
#define MAX_COMMANDS 128
+#define AGI_NANDFS_RETRY 3
+#define AGI_BUF_LEN 2048
/* Recycle some stuff from the CLI interface */
#define fdprintf agi_debug_cli
@@ -1823,7 +1825,6 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
}
return 0;
}
-#define RETRY 3
static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead)
{
struct ast_channel *c;
@@ -1831,11 +1832,11 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
int ms;
enum agi_result returnstatus = AGI_RESULT_SUCCESS;
struct ast_frame *f;
- char buf[2048];
+ char buf[AGI_BUF_LEN];
FILE *readf;
/* how many times we'll retry if ast_waitfor_nandfs will return without either
channel or file descriptor in case select is interrupted by a system call (EINTR) */
- int retry = RETRY;
+ int retry = AGI_NANDFS_RETRY;
if (!(readf = fdopen(agi->ctrl, "r"))) {
ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
@@ -1850,7 +1851,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
ms = -1;
c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
if (c) {
- retry = RETRY;
+ retry = AGI_NANDFS_RETRY;
/* Idle the channel until we get a command */
f = ast_read(c);
if (!f) {
@@ -1866,9 +1867,25 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
ast_frfree(f);
}
} else if (outfd > -1) {
- retry = RETRY;
+ size_t len = sizeof(buf);
+ size_t buflen = 0;
+
+ retry = AGI_NANDFS_RETRY;
buf[0] = '\0';
- if (!fgets(buf, sizeof(buf), readf)) {
+
+ while (buflen < (len - 1)) {
+ fgets(buf + buflen, len, readf);
+ if (feof(readf))
+ break;
+ if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN)))
+ break;
+ buflen = strlen(buf);
+ len -= buflen;
+ if (agidebug)
+ ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno));
+ }
+
+ if (!buf[0]) {
/* Program terminated */
if (returnstatus)
returnstatus = -1;
@@ -1880,6 +1897,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
pid = -1;
break;
}
+
/* get rid of trailing newline, if any */
if (*buf && buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = 0;
@@ -1993,7 +2011,7 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
enum agi_result res;
struct ast_module_user *u;
char *argv[MAX_ARGS];
- char buf[2048]="";
+ char buf[AGI_BUF_LEN] = "";
char *tmp = (char *)buf;
int argc = 0;
int fds[2];