diff options
author | Tilghman Lesher <tilghman@meg.abyt.es> | 2008-04-16 22:57:54 +0000 |
---|---|---|
committer | Tilghman Lesher <tilghman@meg.abyt.es> | 2008-04-16 22:57:54 +0000 |
commit | 123ac5fd646cb7a0ed3b7055cda609db93c20487 (patch) | |
tree | 6dea5b8c8d8bb81a47195b75172db608ff217382 /main | |
parent | 752f6681b1ea748a1acef2a55e17c4c564715fde (diff) |
Standardized routines for forking processes (keeps all the specialized code in one place).
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@114188 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r-- | main/app.c | 63 | ||||
-rw-r--r-- | main/asterisk.c | 6 | ||||
-rw-r--r-- | main/logger.c | 49 |
3 files changed, 113 insertions, 5 deletions
diff --git a/main/app.c b/main/app.c index ee72d1078..05cdf1748 100644 --- a/main/app.c +++ b/main/app.c @@ -32,6 +32,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #endif #include <regex.h> #include <sys/file.h> /* added this to allow to compile, sorry! */ +#include <signal.h> #include "asterisk/paths.h" /* use ast_config_AST_DATA_DIR */ #include "asterisk/channel.h" @@ -1759,3 +1760,65 @@ int ast_get_encoded_char(const char *stream, char *result, size_t *consumed) return 0; } +void ast_close_fds_above_n(int n) +{ + int x, null; + null = open("/dev/null", O_RDONLY); + for (x = n + 1; x <= (null >= 8192 ? null : 8192); x++) { + if (x != null) { + /* Side effect of dup2 is that it closes any existing fd without error. + * This prevents valgrind and other debugging tools from sending up + * false error reports. */ + dup2(null, x); + close(x); + } + } + close(null); +} + +int ast_safe_fork(int stop_reaper) +{ + sigset_t signal_set, old_set; + int pid; + + /* Don't let the default signal handler for children reap our status */ + if (stop_reaper) { + ast_replace_sigchld(); + } + + sigfillset(&signal_set); + pthread_sigmask(SIG_BLOCK, &signal_set, &old_set); + + pid = fork(); + + if (pid != 0) { + /* Fork failed or parent */ + pthread_sigmask(SIG_SETMASK, &old_set, NULL); + return pid; + } else { + /* Child */ + + /* 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 (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) { + ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno)); + _exit(1); + } + + return pid; + } +} + +void ast_safe_fork_cleanup(void) +{ + ast_unreplace_sigchld(); +} + diff --git a/main/asterisk.c b/main/asterisk.c index f08a4d020..99df3ef45 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -848,9 +848,6 @@ void ast_unreplace_sigchld(void) int ast_safe_system(const char *s) { pid_t pid; -#ifdef HAVE_WORKING_FORK - int x; -#endif int res; struct rusage rusage; int status; @@ -869,8 +866,7 @@ int ast_safe_system(const char *s) if (ast_opt_high_priority) ast_set_priority(0); /* Close file descriptors and launch system command */ - for (x = STDERR_FILENO + 1; x < 4096; x++) - close(x); + ast_close_fds_above_n(STDERR_FILENO); #endif execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL); _exit(1); diff --git a/main/logger.c b/main/logger.c index b7c517fa7..dce2097d9 100644 --- a/main/logger.c +++ b/main/logger.c @@ -413,6 +413,55 @@ static void init_logger_chain(int reload, int locked) ast_config_destroy(cfg); } +void ast_child_verbose(int level, const char *fmt, ...) +{ + char *msg = NULL, *emsg = NULL, *sptr, *eptr; + va_list ap, aq; + int size; + + /* Don't bother, if the level isn't that high */ + if (option_verbose < level) { + return; + } + + va_start(ap, fmt); + va_copy(aq, ap); + if ((size = vsnprintf(msg, 0, fmt, ap)) < 0) { + va_end(ap); + va_end(aq); + return; + } + va_end(ap); + + if (!(msg = ast_malloc(size + 1))) { + va_end(aq); + return; + } + + vsnprintf(msg, size + 1, fmt, aq); + va_end(aq); + + if (!(emsg = ast_malloc(size * 2 + 1))) { + ast_free(msg); + return; + } + + for (sptr = msg, eptr = emsg; ; sptr++) { + if (*sptr == '"') { + *eptr++ = '\\'; + } + *eptr++ = *sptr; + if (*sptr == '\0') { + break; + } + } + ast_free(msg); + + fprintf(stdout, "verbose \"%s\" %d\n", emsg, level); + fflush(stdout); + ast_free(emsg); +} + void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...) { va_list ap; |