Index: utils.c =================================================================== --- utils.c (revision 10067) +++ utils.c (working copy) @@ -34,6 +34,7 @@ #include #include #include +#include #include "asterisk.h" @@ -961,6 +962,32 @@ s[ofs] = '\0'; } +int ast_get_maxfd(void) +{ +#ifdef __linux__ + DIR *dir; + struct dirent *entry; + char last[256], path[256]; + int res = 0; + + snprintf(path, sizeof(path), "/proc/%d/fd", (int)getpid()); + + if (!(dir = opendir(path))) { + ast_log(LOG_WARNING, "Could not open %s: all file descriptors may not be closed properly\n", path); + return 0; + } + + while ((entry = readdir(dir))) { + ast_copy_string(last, entry->d_name, sizeof(last)); + } + + sscanf(last, "%d", &res); + return res; +#else + return 0; +#endif +} + const char __ast_string_field_empty[] = ""; static int add_string_pool(struct ast_string_field_mgr *mgr, size_t size) Index: apps/app_zapras.c =================================================================== --- apps/app_zapras.c (revision 10067) +++ apps/app_zapras.c (working copy) @@ -83,7 +83,7 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args) { pid_t pid; - int x; + int x, maxfd; char *c; char *argv[PPP_MAX_ARGS]; @@ -98,8 +98,10 @@ /* Execute RAS on File handles */ dup2(chan->fds[0], STDIN_FILENO); + maxfd = (ast_get_maxfd() || 1024); + /* Close other file descriptors */ - for (x=STDERR_FILENO + 1;x<1024;x++) + for (x = STDERR_FILENO + 1; x <= maxfd; x++) close(x); /* Restore original signal handlers */ Index: apps/app_festival.c =================================================================== --- apps/app_festival.c (revision 10067) +++ apps/app_festival.c (working copy) @@ -127,22 +127,23 @@ return buff; } -static int send_waveform_to_fd(char *waveform, int length, int fd) { - - int res; - int x; +static int send_waveform_to_fd(char *waveform, int length, int fd) +{ + int res; + int x, maxfd; #ifdef __PPC__ char c; #endif - res = fork(); - if (res < 0) - ast_log(LOG_WARNING, "Fork failed\n"); - if (res) - return res; - for (x=0;x<256;x++) { - if (x != fd) - close(x); + res = fork(); + if (res < 0) + ast_log(LOG_WARNING, "Fork failed\n"); + if (res) + return res; + maxfd = (ast_get_maxfd() || 1024); + for (x = 0; x <= maxfd; x++) { + if (x != fd) + close(x); } /*IAS */ #ifdef __PPC__ Index: apps/app_mp3.c =================================================================== --- apps/app_mp3.c (revision 10067) +++ apps/app_mp3.c (working copy) @@ -67,14 +67,15 @@ static int mp3play(char *filename, int fd) { int res; - int x; + int x, maxfd; res = fork(); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) return res; + maxfd = (ast_get_maxfd() || 1024); dup2(fd, STDOUT_FILENO); - for (x=0;x<256;x++) { + for (x = 0; x <= maxfd; x++) { if (x != STDOUT_FILENO) close(x); } Index: apps/app_ices.c =================================================================== --- apps/app_ices.c (revision 10067) +++ apps/app_ices.c (working copy) @@ -69,13 +69,17 @@ { int res; int x; + unsigned int maxfd; + res = fork(); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) return res; dup2(fd, STDIN_FILENO); - for (x=STDERR_FILENO + 1;x<256;x++) { + maxfd = (ast_get_maxfd() || 4096); + + for (x = STDERR_FILENO + 1; x <= maxfd; x++) { if ((x != STDIN_FILENO) && (x != STDOUT_FILENO)) close(x); } Index: apps/app_nbscat.c =================================================================== --- apps/app_nbscat.c (revision 10067) +++ apps/app_nbscat.c (working copy) @@ -71,14 +71,15 @@ static int NBScatplay(int fd) { int res; - int x; + int x, maxfd; res = fork(); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) return res; dup2(fd, STDOUT_FILENO); - for (x=0;x<256;x++) { + maxfd = (ast_get_maxfd() || 1024); + for (x = 0; x <= maxfd; x++) { if (x != STDOUT_FILENO) close(x); } Index: apps/app_externalivr.c =================================================================== --- apps/app_externalivr.c (revision 10067) +++ apps/app_externalivr.c (working copy) @@ -315,12 +315,14 @@ if (!pid) { /* child process */ - int i; + int i, maxfd; dup2(child_stdin[0], STDIN_FILENO); dup2(child_stdout[1], STDOUT_FILENO); dup2(child_stderr[1], STDERR_FILENO); - for (i = STDERR_FILENO + 1; i < 1024; i++) + + maxfd = (ast_get_maxfd() || 1024); + for (i = STDERR_FILENO + 1; i <= maxfd; i++) close(i); execv(argv[0], argv); fprintf(stderr, "Failed to execute '%s': %s\n", argv[0], strerror(errno)); Index: include/asterisk/utils.h =================================================================== --- include/asterisk/utils.h (revision 10067) +++ include/asterisk/utils.h (working copy) @@ -246,6 +246,14 @@ long int ast_random(void); #endif +/*! \brief Retrieve the maximum file descriptor currently open + * \return Returns the maximum FD open or 0 on error. + * + * Useful for making sure that we close all file descriptors in a child + * process. Only works on Linux for the time being. + */ +int ast_get_maxfd(void); + /*! \brief A wrapper for malloc() Index: asterisk.c =================================================================== --- asterisk.c (revision 10067) +++ asterisk.c (working copy) @@ -420,8 +420,9 @@ pid = fork(); if (pid == 0) { + int maxfd = (ast_get_maxfd() || 4096); /* Close file descriptors and launch system command */ - for (x = STDERR_FILENO + 1; x < 4096; x++) + for (x = STDERR_FILENO + 1; x <= maxfd; x++) close(x); execl("/bin/sh", "/bin/sh", "-c", s, NULL); exit(1); Index: res/res_agi.c =================================================================== --- res/res_agi.c (revision 10067) +++ res/res_agi.c (working copy) @@ -222,7 +222,6 @@ int toast[2]; int fromast[2]; int audio[2]; - int x; int res; sigset_t signal_set; @@ -272,6 +271,8 @@ return -1; } if (!pid) { + int x, maxfd; + /* Pass paths to AGI via environmental variables */ setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1); setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1); @@ -300,7 +301,8 @@ } /* Close everything but stdin/out/error */ - for (x=STDERR_FILENO + 2;x<1024;x++) + maxfd = (ast_get_maxfd() || 1024); + for (x = STDERR_FILENO + 2; x <= maxfd; x++) close(x); /* Don't run AGI scripts with realtime priority -- it causes audio stutter */ Index: res/res_musiconhold.c =================================================================== --- res/res_musiconhold.c (revision 10067) +++ res/res_musiconhold.c (working copy) @@ -436,12 +436,13 @@ return -1; } if (!class->pid) { - int x; + int x, maxfd; close(fds[0]); /* Stdout goes to pipe */ dup2(fds[1], STDOUT_FILENO); /* Close unused file descriptors */ - for (x=3;x<8192;x++) { + maxfd = (ast_get_maxfd() || 8192); + for (x = 3; x <= maxfd; x++) { if (-1 != fcntl(x, F_GETFL)) { close(x); }