Index: res/res_agi.c =================================================================== --- res/res_agi.c (revision 34874) +++ res/res_agi.c (working copy) @@ -282,28 +282,46 @@ return -1; } if (!pid) { + int maxfd = 1024; + /* Don't run AGI scripts with realtime priority -- it causes audio stutter */ ast_set_priority(0); + /* unblock important signal handlers */ + if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) { + ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno)); + exit(1); + } + + /* It would suck, greatly, if we didn't close all open file + * descriptors. Luckily, these should be near the top, since they were + * opened recently. */ + if (fromast[1] > maxfd) + maxfd = fromast[1]; + if (toast[1] > maxfd) + maxfd = toast[1]; + if (efd && audio[1] > maxfd) + maxfd = audio[1]; + + /* Bump it up a little, just to be sure we get all fd's */ + maxfd += 10; + + /* Close everything but the fd's we need (which will become stdin/stdout/audio) */ + for (x = 0; x < maxfd; x++) { + if (x != fromast[0] && x != toast[1] && x != STDERR_FILENO && ((efd && x != audio[0]) || (!efd))) + close(x); + } + /* Redirect stdin and out, provide enhanced audio channel if desired */ dup2(fromast[0], STDIN_FILENO); + close(fromast[0]); dup2(toast[1], STDOUT_FILENO); + close(toast[1]); if (efd) { dup2(audio[0], STDERR_FILENO + 1); - } else { - close(STDERR_FILENO + 1); + close(audio[0]); } - - /* unblock important signal handlers */ - if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) { - ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno)); - exit(1); - } - /* Close everything but stdin/out/error */ - for (x=STDERR_FILENO + 2;x<1024;x++) - close(x); - /* Execute script */ execv(script, argv); /* Can't use ast_log since FD's are closed */ @@ -328,7 +346,6 @@ *opid = pid; return 0; - } static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced)