aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authordiruggles <diruggles@f38db490-d61c-443f-a65b-d21fe96a405b>2009-12-03 14:47:57 +0000
committerdiruggles <diruggles@f38db490-d61c-443f-a65b-d21fe96a405b>2009-12-03 14:47:57 +0000
commit264e52dada64a3b6ad6bcff245d0af1b33044779 (patch)
treedd02dd6b6d672a1949344946736fd2d071ec20a4 /apps
parentde728334c2d6c8c48b8e07302b4ba6fe3d3bb973 (diff)
Merged revisions 232587 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r232587 | diruggles | 2009-12-02 17:17:22 -0500 (Wed, 02 Dec 2009) | 12 lines Prevent double closing of FDs by EIVR This caused a problem when asterisk was under heavy load and running both AGI and EIVR applications. EIVR would close an FD at which point it would be considered freed and be used by a new AGI instance the second close would then close the FD now in use by AGI. (closes issue #16305) Reported by: diLLec Tested by: thedavidfactor, diLLec Review: https://reviewboard.asterisk.org/r/436/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@232811 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rw-r--r--apps/app_externalivr.c115
1 files changed, 57 insertions, 58 deletions
diff --git a/apps/app_externalivr.c b/apps/app_externalivr.c
index 1d08b2646..41631913c 100644
--- a/apps/app_externalivr.c
+++ b/apps/app_externalivr.c
@@ -93,7 +93,7 @@ struct gen_state {
};
static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
- int eivr_events_fd, int eivr_commands_fd, int eivr_errors_fd,
+ int *eivr_events_fd, int *eivr_commands_fd, int *eivr_errors_fd,
const char *args);
static void send_eivr_event(FILE *handle, const char event, const char *data,
@@ -297,9 +297,9 @@ static struct playlist_entry *make_entry(const char *filename)
static int app_exec(struct ast_channel *chan, void *data)
{
struct playlist_entry *entry;
- int child_stdin[2] = { 0,0 };
- int child_stdout[2] = { 0,0 };
- int child_stderr[2] = { 0,0 };
+ int child_stdin[2] = { -1, -1 };
+ int child_stdout[2] = { -1, -1 };
+ int child_stderr[2] = { -1, -1 };
int res = -1;
int gen_active = 0;
int pid;
@@ -389,44 +389,44 @@ static int app_exec(struct ast_channel *chan, void *data)
/* parent process */
close(child_stdin[0]);
- child_stdin[0] = 0;
+ child_stdin[0] = -1;
close(child_stdout[1]);
- child_stdout[1] = 0;
+ child_stdout[1] = -1;
close(child_stderr[1]);
- child_stderr[1] = 0;
- res = eivr_comm(chan, u, child_stdin[1], child_stdout[0], child_stderr[0], comma_delim_argbuf);
-
- exit:
- if (gen_active)
- ast_deactivate_generator(chan);
-
- if (child_stdin[0])
- close(child_stdin[0]);
-
- if (child_stdin[1])
- close(child_stdin[1]);
-
- if (child_stdout[0])
- close(child_stdout[0]);
-
- if (child_stdout[1])
- close(child_stdout[1]);
-
- if (child_stderr[0])
- close(child_stderr[0]);
-
- if (child_stderr[1])
- close(child_stderr[1]);
-
- while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
- ast_free(entry);
+ child_stderr[1] = -1;
+ res = eivr_comm(chan, u, &child_stdin[1], &child_stdout[0], &child_stderr[0], comma_delim_argbuf);
+ }
- return res;
+ exit:
+ if (gen_active) {
+ ast_deactivate_generator(chan);
}
+ if (child_stdin[0] > -1) {
+ close(child_stdin[0]);
+ }
+ if (child_stdin[1] > -1) {
+ close(child_stdin[1]);
+ }
+ if (child_stdout[0] > -1) {
+ close(child_stdout[0]);
+ }
+ if (child_stdout[1] > -1) {
+ close(child_stdout[1]);
+ }
+ if (child_stderr[0] > -1) {
+ close(child_stderr[0]);
+ }
+ if (child_stderr[1] > -1) {
+ close(child_stderr[1]);
+ }
+ while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
+ ast_free(entry);
+ }
+ return res;
}
static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
- int eivr_events_fd, int eivr_commands_fd, int eivr_errors_fd,
+ int *eivr_events_fd, int *eivr_commands_fd, int *eivr_errors_fd,
const char *args)
{
struct playlist_entry *entry;
@@ -434,7 +434,7 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
int ms;
int exception;
int ready_fd;
- int waitfds[2] = { eivr_commands_fd, eivr_errors_fd };
+ int waitfds[2] = { *eivr_commands_fd, (eivr_errors_fd) ? *eivr_errors_fd : -1 };
struct ast_channel *rchan;
char *command;
int res = -1;
@@ -444,16 +444,16 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
FILE *eivr_errors = NULL;
FILE *eivr_events = NULL;
- if (!(eivr_events = fdopen(eivr_events_fd, "w"))) {
+ if (!(eivr_events = fdopen(*eivr_events_fd, "w"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream to send events\n");
goto exit;
}
- if (!(eivr_commands = fdopen(eivr_commands_fd, "r"))) {
+ if (!(eivr_commands = fdopen(*eivr_commands_fd, "r"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive commands\n");
goto exit;
}
- if(eivr_errors_fd) { /*if opening a socket connection, error stream will not be used*/
- if (!(eivr_errors = fdopen(eivr_errors_fd, "r"))) {
+ if (eivr_errors_fd) { /*if opening a socket connection, error stream will not be used*/
+ if (!(eivr_errors = fdopen(*eivr_errors_fd, "r"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive errors\n");
goto exit;
}
@@ -486,7 +486,7 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
errno = 0;
exception = 0;
- rchan = ast_waitfor_nandfds(&chan, 1, waitfds, (eivr_errors_fd == 0) ? 1 : 2, &exception, &ready_fd, &ms);
+ rchan = ast_waitfor_nandfds(&chan, 1, waitfds, (eivr_errors_fd) ? 2 : 1, &exception, &ready_fd, &ms);
if (!AST_LIST_EMPTY(&u->finishlist)) {
AST_LIST_LOCK(&u->finishlist);
@@ -528,10 +528,10 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
break;
}
ast_frfree(f);
- } else if (ready_fd == eivr_commands_fd) {
+ } else if (ready_fd == *eivr_commands_fd) {
char input[1024];
- if (exception || (dup2(eivr_commands_fd, test_available_fd) == -1) || feof(eivr_commands)) {
+ if (exception || (dup2(*eivr_commands_fd, test_available_fd) == -1) || feof(eivr_commands)) {
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
res = -1;
break;
@@ -618,7 +618,7 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
else
ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]);
}
- } else if (eivr_errors_fd && ready_fd == eivr_errors_fd) {
+ } else if (eivr_errors_fd && (ready_fd == *eivr_errors_fd)) {
char input[1024];
if (exception || feof(eivr_errors)) {
@@ -638,26 +638,25 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
break;
}
}
-
-
-exit:
-
+
+ exit:
if (test_available_fd > -1) {
close(test_available_fd);
}
-
- if (eivr_events)
+ if (eivr_events) {
fclose(eivr_events);
-
- if (eivr_commands)
+ *eivr_events_fd = -1;
+ }
+ if (eivr_commands) {
fclose(eivr_commands);
-
- if (eivr_errors)
+ *eivr_commands_fd = -1;
+ }
+ if (eivr_errors) {
fclose(eivr_errors);
-
- return res;
-
- }
+ *eivr_errors_fd = -1;
+ }
+ return res;
+ }
static int unload_module(void)
{