]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 48375 via svnmerge from
authorTilghman Lesher <tilghman@meg.abyt.es>
Mon, 11 Dec 2006 00:52:19 +0000 (00:52 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Mon, 11 Dec 2006 00:52:19 +0000 (00:52 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

................
r48375 | tilghman | 2006-12-10 18:47:21 -0600 (Sun, 10 Dec 2006) | 13 lines

Merged revisions 48374 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r48374 | tilghman | 2006-12-10 18:33:59 -0600 (Sun, 10 Dec 2006) | 5 lines

When doing a fork() and exec(), two problems existed (Issue 8086):
1) Ignored signals stayed ignored after the exec().
2) Signals could possibly fire between the fork() and exec(), causing Asterisk
signal handlers within the child to execute, which caused nasty race conditions.

........

................

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@48376 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_externalivr.c
apps/app_festival.c
apps/app_ices.c
apps/app_mp3.c
apps/app_nbscat.c
apps/app_zapras.c
res/res_agi.c
res/res_musiconhold.c

index f9b8905884c130721b280de3b4f6394a91495a4c..bcda8d6634651f0dcae6b9717e5d4755f0c80677 100644 (file)
@@ -40,6 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
+#include <signal.h>
 
 #include "asterisk/lock.h"
 #include "asterisk/file.h"
@@ -262,9 +263,13 @@ static int app_exec(struct ast_channel *chan, void *data)
                .finishlist = AST_LIST_HEAD_INIT_VALUE,
        };
        struct ivr_localuser *u = &foo;
+       sigset_t fullset, oldset;
 
        lu = ast_module_user_add(chan);
-       
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
        u->abort_current_sound = 0;
        u->chan = chan;
        
@@ -313,6 +318,9 @@ static int app_exec(struct ast_channel *chan, void *data)
                /* child process */
                int i;
 
+               signal(SIGPIPE, SIG_DFL);
+               pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
                if (ast_opt_high_priority)
                        ast_set_priority(0);
 
@@ -336,6 +344,8 @@ static int app_exec(struct ast_channel *chan, void *data)
                int waitfds[2] = { child_errors_fd, child_commands_fd };
                struct ast_channel *rchan;
 
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+
                close(child_stdin[0]);
                child_stdin[0] = 0;
                close(child_stdout[1]);
index e0245987387820b2321ef0402f538fa6353d51c0..7af2e78a6a1b7a389ae8da723ffba38319967eaa 100644 (file)
@@ -130,19 +130,26 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
 #ifdef __PPC__ 
        char c;
 #endif
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
 
         res = fork();
         if (res < 0)
                 ast_log(LOG_WARNING, "Fork failed\n");
-        if (res)
+        if (res) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                 return res;
+       }
         for (x=0;x<256;x++) {
                 if (x != fd)
                         close(x);
         }
        if (ast_opt_high_priority)
                ast_set_priority(0);
-
+       signal(SIGPIPE, SIG_DFL);
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
 /*IAS */
 #ifdef __PPC__  
        for( x=0; x<length; x+=2)
index 869254738fc594edac5d9466fdd8906b4d18984d..91725fdc6b26eaf0b839a2b1eb08e5b049e3907e 100644 (file)
@@ -65,15 +65,27 @@ static int icesencode(char *filename, int fd)
 {
        int res;
        int x;
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
        res = fork();
        if (res < 0) 
                ast_log(LOG_WARNING, "Fork failed\n");
-       if (res)
+       if (res) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                return res;
+       }
+
+       /* Stop ignoring PIPE */
+       signal(SIGPIPE, SIG_DFL);
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
        if (ast_opt_high_priority)
                ast_set_priority(0);
        dup2(fd, STDIN_FILENO);
-       for (x=STDERR_FILENO + 1;x<256;x++) {
+       for (x=STDERR_FILENO + 1;x<1024;x++) {
                if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
                        close(x);
        }
@@ -84,7 +96,7 @@ static int icesencode(char *filename, int fd)
        /* As a last-ditch effort, try to use PATH */
        execlp("ices", "ices", filename, (char *)NULL);
        ast_log(LOG_WARNING, "Execute of ices failed\n");
-       return -1;
+       _exit(0);
 }
 
 static int ices_exec(struct ast_channel *chan, void *data)
index 704666d8f6da141472ddd2404aca41184b1f8a86..e0df37d61ebf944149e2ac450992d0365e9d31f7 100644 (file)
@@ -64,15 +64,25 @@ static int mp3play(char *filename, int fd)
 {
        int res;
        int x;
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
        res = fork();
        if (res < 0) 
                ast_log(LOG_WARNING, "Fork failed\n");
-       if (res)
+       if (res) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                return res;
+       }
        if (ast_opt_high_priority)
                ast_set_priority(0);
+       signal(SIGPIPE, SIG_DFL);
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
        dup2(fd, STDOUT_FILENO);
-       for (x=0;x<256;x++) {
+       for (x=STDERR_FILENO + 1;x<256;x++) {
                if (x != STDOUT_FILENO)
                        close(x);
        }
@@ -94,7 +104,7 @@ static int mp3play(char *filename, int fd)
            execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
        }
        ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
-       return -1;
+       _exit(0);
 }
 
 static int timed_read(int fd, void *data, int datalen, int timeout)
index 60623cc9370597ae814226d04c81a948f15640af..1fb51e688ad448ac27552ef8ba654e7b208be6c6 100644 (file)
@@ -68,16 +68,26 @@ static int NBScatplay(int fd)
 {
        int res;
        int x;
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
        res = fork();
        if (res < 0) 
                ast_log(LOG_WARNING, "Fork failed\n");
-       if (res)
+       if (res) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                return res;
+       }
+       signal(SIGPIPE, SIG_DFL);
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
        if (ast_opt_high_priority)
                ast_set_priority(0);
 
        dup2(fd, STDOUT_FILENO);
-       for (x=0;x<256;x++) {
+       for (x = STDERR_FILENO + 1; x < 1024; x++) {
                if (x != STDOUT_FILENO)
                        close(x);
        }
@@ -85,7 +95,7 @@ static int NBScatplay(int fd)
        execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
        execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
        ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
-       return -1;
+       _exit(0);
 }
 
 static int timed_read(int fd, void *data, int datalen)
index 9e841603c4275b7ff8bf85550879e5d908fc28a0..7b85f70402ed4eecfedf25c7d583358dd2406458 100644 (file)
@@ -82,11 +82,23 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
        char *argv[PPP_MAX_ARGS];
        int argc = 0;
        char *stringp=NULL;
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
 
        /* Start by forking */
        pid = fork();
-       if (pid)
+       if (pid) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                return pid;
+       }
+
+       /* Restore original signal handlers */
+       for (x=0;x<NSIG;x++)
+               signal(x, SIG_DFL);
+
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
 
        /* Execute RAS on File handles */
        dup2(chan->fds[0], STDIN_FILENO);
@@ -99,10 +111,6 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
        for (x=STDERR_FILENO + 1;x<1024;x++) 
                close(x);
 
-       /* Restore original signal handlers */
-       for (x=0;x<NSIG;x++)
-               signal(x, SIG_DFL);
-
        /* Reset all arguments */
        memset(argv, 0, sizeof(argv));
 
index b4d61702514921294025c51872c288829e9b67a6..042fdbfbca42ce47ca86ea958719f2d382c17961 100644 (file)
@@ -241,7 +241,7 @@ static enum agi_result launch_script(char *script, char *argv[], int *fds, int *
        int audio[2];
        int x;
        int res;
-       sigset_t signal_set;
+       sigset_t signal_set, old_set;
        
        if (!strncasecmp(script, "agi://", 6))
                return launch_netscript(script, argv, fds, efd, opid);
@@ -283,11 +283,14 @@ static enum agi_result launch_script(char *script, char *argv[], int *fds, int *
                        return AGI_RESULT_FAILURE;
                }
        }
-       ast_replace_sigchld();
+
+       /* Block SIGHUP during the fork - prevents a race */
+       sigfillset(&signal_set);
+       pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
        pid = fork();
        if (pid < 0) {
                ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
-               ast_unreplace_sigchld();
+               pthread_sigmask(SIG_SETMASK, &old_set, NULL);
                return AGI_RESULT_FAILURE;
        }
        if (!pid) {
@@ -315,9 +318,18 @@ static enum agi_result launch_script(char *script, char *argv[], int *fds, int *
                } else {
                        close(STDERR_FILENO + 1);
                }
-               
+
+               /* Before we unblock our signals, return our trapped signals back to the defaults */
+               signal(SIGHUP, SIG_DFL);
+               signal(SIGCHLD, SIG_DFL);
+               signal(SIGINT, SIG_DFL);
+               signal(SIGURG, SIG_DFL);
+               signal(SIGTERM, SIG_DFL);
+               signal(SIGPIPE, SIG_DFL);
+               signal(SIGXFSZ, SIG_DFL);
+
                /* unblock important signal handlers */
-               if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
+               if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
                        ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
                        _exit(1);
                }
@@ -334,6 +346,7 @@ static enum agi_result launch_script(char *script, char *argv[], int *fds, int *
                fflush(stdout);
                _exit(1);
        }
+       pthread_sigmask(SIG_SETMASK, &old_set, NULL);
        if (option_verbose > 2) 
                ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
        fds[0] = toast[0];
@@ -350,7 +363,6 @@ static enum agi_result launch_script(char *script, char *argv[], int *fds, int *
 
        *opid = pid;
        return AGI_RESULT_SUCCESS;
-               
 }
 
 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
index f560432bb5e521580dd9808c0955ac2ab9a45bde..96e24a4a7d551f43be8702c8c4fca273507b272e 100644 (file)
@@ -340,6 +340,7 @@ static int spawn_mp3(struct mohclass *class)
        int argc = 0;
        DIR *dir = NULL;
        struct dirent *de;
+       sigset_t signal_set, old_set;
 
        
        if (!strcasecmp(class->dir, "nodir")) {
@@ -424,6 +425,11 @@ static int spawn_mp3(struct mohclass *class)
        if (time(NULL) - class->start < respawn_time) {
                sleep(respawn_time - (time(NULL) - class->start));
        }
+
+       /* Block signals during the fork() */
+       sigfillset(&signal_set);
+       pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
+
        time(&class->start);
        class->pid = fork();
        if (class->pid < 0) {
@@ -438,6 +444,10 @@ static int spawn_mp3(struct mohclass *class)
                if (ast_opt_high_priority)
                        ast_set_priority(0);
 
+               /* Reset ignored signals back to default */
+               signal(SIGPIPE, SIG_DFL);
+               pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
+
                close(fds[0]);
                /* Stdout goes to pipe */
                dup2(fds[1], STDOUT_FILENO);
@@ -464,6 +474,7 @@ static int spawn_mp3(struct mohclass *class)
                _exit(1);
        } else {
                /* Parent */
+               pthread_sigmask(SIG_SETMASK, &old_set, NULL);
                close(fds[1]);
        }
        return fds[0];