mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-30 10:33:13 +00:00
Merged revisions 82245 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r82245 | russell | 2007-09-11 10:26:51 -0500 (Tue, 11 Sep 2007) | 9 lines (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: https://origsvn.digium.com/svn/asterisk/trunk@82246 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -67,6 +67,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
#include "asterisk/agi.h"
|
#include "asterisk/agi.h"
|
||||||
|
|
||||||
#define MAX_ARGS 128
|
#define MAX_ARGS 128
|
||||||
|
#define AGI_NANDFS_RETRY 3
|
||||||
|
#define AGI_BUF_LEN 2048
|
||||||
|
|
||||||
static char *app = "AGI";
|
static char *app = "AGI";
|
||||||
|
|
||||||
@@ -1856,18 +1858,17 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int
|
|||||||
}
|
}
|
||||||
return 0;
|
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, int argc, char *argv[])
|
static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct ast_channel *c;
|
struct ast_channel *c;
|
||||||
int outfd, ms, needhup = 0;
|
int outfd, ms, needhup = 0;
|
||||||
enum agi_result returnstatus = AGI_RESULT_SUCCESS;
|
enum agi_result returnstatus = AGI_RESULT_SUCCESS;
|
||||||
struct ast_frame *f;
|
struct ast_frame *f;
|
||||||
char buf[2048];
|
char buf[AGI_BUF_LEN];
|
||||||
FILE *readf;
|
FILE *readf;
|
||||||
/* how many times we'll retry if ast_waitfor_nandfs will return without either
|
/* 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) */
|
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"))) {
|
if (!(readf = fdopen(agi->ctrl, "r"))) {
|
||||||
ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
|
ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
|
||||||
@@ -1887,7 +1888,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
|||||||
ms = -1;
|
ms = -1;
|
||||||
c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
|
c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
|
||||||
if (c) {
|
if (c) {
|
||||||
retry = RETRY;
|
retry = AGI_NANDFS_RETRY;
|
||||||
/* Idle the channel until we get a command */
|
/* Idle the channel until we get a command */
|
||||||
f = ast_read(c);
|
f = ast_read(c);
|
||||||
if (!f) {
|
if (!f) {
|
||||||
@@ -1904,9 +1905,25 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
|||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
}
|
}
|
||||||
} else if (outfd > -1) {
|
} else if (outfd > -1) {
|
||||||
retry = RETRY;
|
size_t len = sizeof(buf);
|
||||||
|
size_t buflen = 0;
|
||||||
|
|
||||||
|
retry = AGI_NANDFS_RETRY;
|
||||||
buf[0] = '\0';
|
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 */
|
/* Program terminated */
|
||||||
if (returnstatus && returnstatus != AST_PBX_KEEPALIVE)
|
if (returnstatus && returnstatus != AST_PBX_KEEPALIVE)
|
||||||
returnstatus = -1;
|
returnstatus = -1;
|
||||||
@@ -1917,6 +1934,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
|||||||
pid = -1;
|
pid = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get rid of trailing newline, if any */
|
/* get rid of trailing newline, if any */
|
||||||
if (*buf && buf[strlen(buf) - 1] == '\n')
|
if (*buf && buf[strlen(buf) - 1] == '\n')
|
||||||
buf[strlen(buf) - 1] = 0;
|
buf[strlen(buf) - 1] = 0;
|
||||||
@@ -2067,7 +2085,7 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
|
|||||||
{
|
{
|
||||||
enum agi_result res;
|
enum agi_result res;
|
||||||
struct ast_module_user *u;
|
struct ast_module_user *u;
|
||||||
char buf[2048] = "", *tmp = buf;
|
char buf[AGI_BUF_LEN] = "", *tmp = buf;
|
||||||
int fds[2], efd = -1, pid;
|
int fds[2], efd = -1, pid;
|
||||||
AST_DECLARE_APP_ARGS(args,
|
AST_DECLARE_APP_ARGS(args,
|
||||||
AST_APP_ARG(arg)[MAX_ARGS];
|
AST_APP_ARG(arg)[MAX_ARGS];
|
||||||
|
Reference in New Issue
Block a user