]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Use sigaction for signals which should persist past the initial trigger, not signal.
authorTilghman Lesher <tilghman@meg.abyt.es>
Wed, 26 May 2010 21:11:44 +0000 (21:11 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Wed, 26 May 2010 21:11:44 +0000 (21:11 +0000)
If you call signal() in a Solaris signal handler, instead of just resetting
the signal handler, it causes the signal to refire, because the signal is not
marked as handled prior to the signal handler being called.  This effectively
causes Solaris to immediately exceed the threadstack in recursive signal
handlers and crash.

(closes issue #17000)
 Reported by: rmcgilvr
 Patches:
       20100526__issue17000.diff.txt uploaded by tilghman (license 14)
 Tested by: rmcgilvr

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

main/asterisk.c
main/logger.c

index bdf9d5c39c2e38d92224dca75c9b53b4f087c066..236e6318b2101399146467e67d1ef61ad9ca3b94 100644 (file)
@@ -760,16 +760,20 @@ static int fdprint(int fd, const char *s)
 }
 
 /*! \brief NULL handler so we can collect the child exit status */
-static void null_sig_handler(int signal)
+static void _null_sig_handler(int signal)
 {
 
 }
 
+static struct sigaction null_sig_handler = {
+       .sa_handler = _null_sig_handler,
+};
+
 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
 /*! \brief Keep track of how many threads are currently trying to wait*() on
  *  a child process */
 static unsigned int safe_system_level = 0;
-static void *safe_system_prev_handler;
+static struct sigaction safe_system_prev_handler;
 
 void ast_replace_sigchld(void)
 {
@@ -779,8 +783,9 @@ void ast_replace_sigchld(void)
        level = safe_system_level++;
 
        /* only replace the handler if it has not already been done */
-       if (level == 0)
-               safe_system_prev_handler = signal(SIGCHLD, null_sig_handler);
+       if (level == 0) {
+               sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
+       }
 
        ast_mutex_unlock(&safe_system_lock);
 }
@@ -793,8 +798,9 @@ void ast_unreplace_sigchld(void)
        level = --safe_system_level;
 
        /* only restore the handler if we are the last one */
-       if (level == 0)
-               signal(SIGCHLD, safe_system_prev_handler);
+       if (level == 0) {
+               sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
+       }
 
        ast_mutex_unlock(&safe_system_lock);
 }
@@ -1153,13 +1159,16 @@ static int ast_tryconnect(void)
  system call.  We don't actually need to do anything though.  
  Remember: Cannot EVER ast_log from within a signal handler 
  */
-static void urg_handler(int num)
+static void _urg_handler(int num)
 {
-       signal(num, urg_handler);
        return;
 }
 
-static void hup_handler(int num)
+static struct sigaction urg_handler = {
+       .sa_handler = _urg_handler,
+};
+
+static void _hup_handler(int num)
 {
        int a = 0;
        if (option_verbose > 1) 
@@ -1172,10 +1181,13 @@ static void hup_handler(int num)
                        fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
                }
        }
-       signal(num, hup_handler);
 }
 
-static void child_handler(int sig)
+static struct sigaction hup_handler = {
+       .sa_handler = _hup_handler,
+};
+
+static void _child_handler(int sig)
 {
        /* Must not ever ast_log or ast_verbose within signal handler */
        int n, status;
@@ -1187,9 +1199,12 @@ static void child_handler(int sig)
                ;
        if (n == 0 && option_debug)     
                printf("Huh?  Child handler, but nobody there?\n");
-       signal(sig, child_handler);
 }
 
+static struct sigaction child_handler = {
+       .sa_handler = _child_handler,
+};
+
 /*! \brief Set an X-term or screen title */
 static void set_title(char *text)
 {
@@ -1366,7 +1381,7 @@ static void __quit_handler(int num)
        sig_flags.need_quit = 1;
        if (sig_alert_pipe[1] != -1) {
                if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
-                       fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
+                       fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
                }
        }
        /* There is no need to restore the signal handler here, since the app
@@ -3045,11 +3060,11 @@ int main(int argc, char *argv[])
        sigaddset(&sigs, SIGPIPE);
        sigaddset(&sigs, SIGWINCH);
        pthread_sigmask(SIG_BLOCK, &sigs, NULL);
-       signal(SIGURG, urg_handler);
+       sigaction(SIGURG, &urg_handler, NULL);
        signal(SIGINT, __quit_handler);
        signal(SIGTERM, __quit_handler);
-       signal(SIGHUP, hup_handler);
-       signal(SIGCHLD, child_handler);
+       sigaction(SIGHUP, &hup_handler, NULL);
+       sigaction(SIGCHLD, &child_handler, NULL);
        signal(SIGPIPE, SIG_IGN);
 
        /* ensure that the random number generators are seeded with a different value every time
index 99ab0b288b110746281a024353e627159b813c6d..a0beca1cd743b86c3e28c139423dc75e1b91bb58 100644 (file)
@@ -573,26 +573,29 @@ static struct ast_cli_entry cli_logger[] = {
        logger_rotate_help },
 };
 
-static int handle_SIGXFSZ(int sig) 
+static void _handle_SIGXFSZ(int sig)
 {
        /* Indicate need to reload */
        filesize_reload_needed = 1;
-       return 0;
 }
 
+static struct sigaction handle_SIGXFSZ = {
+       .sa_handler = _handle_SIGXFSZ,
+};
+
 int init_logger(void)
 {
        char tmp[256];
        int res = 0;
 
        /* auto rotate if sig SIGXFSZ comes a-knockin */
-       (void) signal(SIGXFSZ,(void *) handle_SIGXFSZ);
+       sigaction(SIGXFSZ, &handle_SIGXFSZ, NULL);
 
        /* register the logger cli commands */
        ast_cli_register_multiple(cli_logger, sizeof(cli_logger) / sizeof(struct ast_cli_entry));
 
        mkdir((char *)ast_config_AST_LOG_DIR, 0755);
-  
+
        /* create log channels */
        init_logger_chain();