aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2006-12-11 00:33:59 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2006-12-11 00:33:59 +0000
commit5125deb3148e6711a6855de8430c4958ed77eaa1 (patch)
tree578d53d159454cd798b99b22d066995d4760791b
parent8f132ae7cbf665bfc3e4385a5a9588b83bf06921 (diff)
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: http://svn.digium.com/svn/asterisk/branches/1.2@48374 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--apps/app_externalivr.c12
-rw-r--r--apps/app_festival.c11
-rw-r--r--apps/app_ices.c18
-rw-r--r--apps/app_mp3.c16
-rw-r--r--apps/app_nbscat.c16
-rw-r--r--apps/app_zapras.c18
-rw-r--r--res/res_agi.c20
-rw-r--r--res/res_musiconhold.c11
8 files changed, 102 insertions, 20 deletions
diff --git a/apps/app_externalivr.c b/apps/app_externalivr.c
index fc5f34082..068463cec 100644
--- a/apps/app_externalivr.c
+++ b/apps/app_externalivr.c
@@ -31,6 +31,7 @@
#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <signal.h>
#include "asterisk.h"
@@ -258,9 +259,13 @@ static int app_exec(struct ast_channel *chan, void *data)
FILE *child_commands = NULL;
FILE *child_errors = NULL;
FILE *child_events = NULL;
+ sigset_t fullset, oldset;
LOCAL_USER_ADD(u);
-
+
+ sigfillset(&fullset);
+ pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
AST_LIST_HEAD_INIT(&u->playlist);
AST_LIST_HEAD_INIT(&u->finishlist);
u->abort_current_sound = 0;
@@ -314,6 +319,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 (option_highpriority)
ast_set_priority(0);
@@ -337,6 +345,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]);
diff --git a/apps/app_festival.c b/apps/app_festival.c
index 7c69dc8b9..33f54aaf3 100644
--- a/apps/app_festival.c
+++ b/apps/app_festival.c
@@ -127,19 +127,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 (option_highpriority)
ast_set_priority(0);
-
+ signal(SIGPIPE, SIG_DFL);
+ pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
/*IAS */
#ifdef __PPC__
for( x=0; x<length; x+=2)
diff --git a/apps/app_ices.c b/apps/app_ices.c
index b6b5ad3f7..5a9b9412d 100644
--- a/apps/app_ices.c
+++ b/apps/app_ices.c
@@ -68,15 +68,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 (option_highpriority)
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);
}
@@ -87,7 +99,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)
diff --git a/apps/app_mp3.c b/apps/app_mp3.c
index 31fc32096..1cba886bb 100644
--- a/apps/app_mp3.c
+++ b/apps/app_mp3.c
@@ -67,15 +67,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 (option_highpriority)
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);
}
@@ -97,7 +107,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)
diff --git a/apps/app_nbscat.c b/apps/app_nbscat.c
index adc232373..004bde77b 100644
--- a/apps/app_nbscat.c
+++ b/apps/app_nbscat.c
@@ -71,16 +71,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 (option_highpriority)
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);
}
@@ -88,7 +98,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)
diff --git a/apps/app_zapras.c b/apps/app_zapras.c
index cf770f2b7..91336f5e4 100644
--- a/apps/app_zapras.c
+++ b/apps/app_zapras.c
@@ -87,11 +87,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);
@@ -104,10 +116,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));
diff --git a/res/res_agi.c b/res/res_agi.c
index 022cee46e..1d39c6936 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -234,7 +234,7 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
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);
@@ -276,6 +276,10 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
return -1;
}
}
+
+ /* 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));
@@ -293,9 +297,18 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
} 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);
}
@@ -310,6 +323,7 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno));
_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];
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index c7f1fff6a..746fa2d06 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -326,6 +326,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")) {
@@ -426,6 +427,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) {
@@ -440,6 +446,10 @@ static int spawn_mp3(struct mohclass *class)
if (option_highpriority)
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);
@@ -466,6 +476,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];