[asterisk-commits] tilghman: branch 1.2 r48374 - in /branches/1.2:
apps/ res/
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Sun Dec 10 17:33:59 MST 2006
Author: tilghman
Date: Sun Dec 10 18:33:59 2006
New Revision: 48374
URL: http://svn.digium.com/view/asterisk?view=rev&rev=48374
Log:
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.
Modified:
branches/1.2/apps/app_externalivr.c
branches/1.2/apps/app_festival.c
branches/1.2/apps/app_ices.c
branches/1.2/apps/app_mp3.c
branches/1.2/apps/app_nbscat.c
branches/1.2/apps/app_zapras.c
branches/1.2/res/res_agi.c
branches/1.2/res/res_musiconhold.c
Modified: branches/1.2/apps/app_externalivr.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/apps/app_externalivr.c?view=diff&rev=48374&r1=48373&r2=48374
==============================================================================
--- branches/1.2/apps/app_externalivr.c (original)
+++ branches/1.2/apps/app_externalivr.c Sun Dec 10 18:33:59 2006
@@ -31,6 +31,7 @@
#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <signal.h>
#include "asterisk.h"
@@ -258,9 +259,13 @@
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;
@@ -313,6 +318,9 @@
if (!pid) {
/* child process */
int i;
+
+ signal(SIGPIPE, SIG_DFL);
+ pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
if (option_highpriority)
ast_set_priority(0);
@@ -336,6 +344,8 @@
int ready_fd;
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;
Modified: branches/1.2/apps/app_festival.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/apps/app_festival.c?view=diff&rev=48374&r1=48373&r2=48374
==============================================================================
--- branches/1.2/apps/app_festival.c (original)
+++ branches/1.2/apps/app_festival.c Sun Dec 10 18:33:59 2006
@@ -127,19 +127,26 @@
#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)
Modified: branches/1.2/apps/app_ices.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/apps/app_ices.c?view=diff&rev=48374&r1=48373&r2=48374
==============================================================================
--- branches/1.2/apps/app_ices.c (original)
+++ branches/1.2/apps/app_ices.c Sun Dec 10 18:33:59 2006
@@ -68,15 +68,27 @@
{
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 @@
/* 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)
Modified: branches/1.2/apps/app_mp3.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/apps/app_mp3.c?view=diff&rev=48374&r1=48373&r2=48374
==============================================================================
--- branches/1.2/apps/app_mp3.c (original)
+++ branches/1.2/apps/app_mp3.c Sun Dec 10 18:33:59 2006
@@ -67,15 +67,25 @@
{
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 @@
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)
Modified: branches/1.2/apps/app_nbscat.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/apps/app_nbscat.c?view=diff&rev=48374&r1=48373&r2=48374
==============================================================================
--- branches/1.2/apps/app_nbscat.c (original)
+++ branches/1.2/apps/app_nbscat.c Sun Dec 10 18:33:59 2006
@@ -71,16 +71,26 @@
{
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 @@
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)
Modified: branches/1.2/apps/app_zapras.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/apps/app_zapras.c?view=diff&rev=48374&r1=48373&r2=48374
==============================================================================
--- branches/1.2/apps/app_zapras.c (original)
+++ branches/1.2/apps/app_zapras.c Sun Dec 10 18:33:59 2006
@@ -87,11 +87,23 @@
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);
@@ -103,10 +115,6 @@
/* Close other file descriptors */
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));
Modified: branches/1.2/res/res_agi.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/res/res_agi.c?view=diff&rev=48374&r1=48373&r2=48374
==============================================================================
--- branches/1.2/res/res_agi.c (original)
+++ branches/1.2/res/res_agi.c Sun Dec 10 18:33:59 2006
@@ -234,7 +234,7 @@
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 @@
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 @@
} 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 @@
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];
Modified: branches/1.2/res/res_musiconhold.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/res/res_musiconhold.c?view=diff&rev=48374&r1=48373&r2=48374
==============================================================================
--- branches/1.2/res/res_musiconhold.c (original)
+++ branches/1.2/res/res_musiconhold.c Sun Dec 10 18:33:59 2006
@@ -326,6 +326,7 @@
int argc = 0;
DIR *dir = NULL;
struct dirent *de;
+ sigset_t signal_set, old_set;
if (!strcasecmp(class->dir, "nodir")) {
@@ -426,6 +427,11 @@
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) {
@@ -439,6 +445,10 @@
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 */
@@ -466,6 +476,7 @@
_exit(1);
} else {
/* Parent */
+ pthread_sigmask(SIG_SETMASK, &old_set, NULL);
close(fds[1]);
}
return fds[0];
More information about the asterisk-commits
mailing list