]> source.dussan.org Git - rspamd.git/commitdiff
* Implement delayed fork of dead workers (to avoid fork bombs)
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Sun, 11 Jan 2009 09:39:37 +0000 (12:39 +0300)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Sun, 11 Jan 2009 09:39:37 +0000 (12:39 +0300)
* Implement refork of controller
* Log time to console in normal view

src/main.c
src/util.c

index e2649e911284895e1477e6164db86191130205f3..454f164ead102a7df11c695083f2a245f4be5715 100644 (file)
@@ -23,6 +23,9 @@
 #include "cfg_file.h"
 #include "util.h"
 
+/* 2 seconds to fork new process in place of dead one */
+#define SOFT_FORK_TIME 2
+
 struct config_file *cfg;
 
 static void sig_handler (int );
@@ -32,6 +35,7 @@ sig_atomic_t do_restart;
 sig_atomic_t do_terminate;
 sig_atomic_t child_dead;
 sig_atomic_t child_ready;
+sig_atomic_t got_alarm;
 
 extern int yynerrs;
 extern FILE *yyin;
@@ -42,6 +46,9 @@ PerlInterpreter *perl_interpreter;
 /* XXX: remove this shit when it would be clear why perl need this line */
 PerlInterpreter *my_perl;
 
+/* List of workers that are pending to start */
+static GList *workers_pending = NULL;
+
 static 
 void sig_handler (int signo)
 {
@@ -60,6 +67,9 @@ void sig_handler (int signo)
                case SIGUSR2:
                        child_ready = 1;
                        break;
+               case SIGALRM:
+                       got_alarm = 1;
+                       break;
        }
 }
 
@@ -124,6 +134,7 @@ fork_worker (struct rspamd_main *rspamd, int listen_sock, int reconfig, enum pro
                bzero (cur, sizeof (struct rspamd_worker));
                TAILQ_INSERT_HEAD (&rspamd->workers, cur, next);
                cur->srv = rspamd;
+               cur->type = type;
                cur->pid = fork();
                switch (cur->pid) {
                        case 0:
@@ -133,7 +144,6 @@ fork_worker (struct rspamd_main *rspamd, int listen_sock, int reconfig, enum pro
                                                setproctitle ("controller process");
                                                pidfile_close (rspamd->pfh);
                                                msg_info ("fork_worker: starting controller process %d", getpid ());
-                                               cur->type = TYPE_CONTROLLER;
                                                start_controller (cur);
                                                break;
                                        case TYPE_WORKER:
@@ -141,7 +151,6 @@ fork_worker (struct rspamd_main *rspamd, int listen_sock, int reconfig, enum pro
                                                setproctitle ("worker process");
                                                pidfile_close (rspamd->pfh);
                                                msg_info ("fork_worker: starting worker process %d", getpid ());
-                                               cur->type = TYPE_WORKER;
                                                start_worker (cur, listen_sock);
                                                break;
                                }
@@ -157,6 +166,26 @@ fork_worker (struct rspamd_main *rspamd, int listen_sock, int reconfig, enum pro
        return cur;
 }
 
+static void
+delay_fork (enum process_type type)
+{
+       workers_pending = g_list_prepend (workers_pending, GINT_TO_POINTER (type));
+       (void)alarm (SOFT_FORK_TIME);
+}
+
+static void
+fork_delayed (struct rspamd_main *rspamd, int listen_sock)
+{
+       GList *cur;
+
+       while (workers_pending != NULL) {
+               cur = workers_pending;
+               workers_pending = g_list_remove_link (workers_pending, cur);
+               fork_worker (rspamd, listen_sock, 0, GPOINTER_TO_INT (cur->data));
+               g_list_free_1 (cur);
+       }
+}
+
 int 
 main (int argc, char **argv, char **env)
 {
@@ -352,25 +381,23 @@ main (int argc, char **argv, char **env)
                                                active_worker = NULL;
                                        }
                                        TAILQ_REMOVE(&rspamd->workers, cur, next);
-                                       if (cur->type == TYPE_CONTROLLER) {
-                                               msg_info ("main: do not restart dead controller");
-                                               g_free (cur);
-                                               break;
-                                       }
                                        if (WIFEXITED (res) && WEXITSTATUS (res) == 0) {
                                                /* Normal worker termination, do not fork one more */
-                                               msg_info ("main: worker process %d terminated normally", cur->pid);
+                                               msg_info ("main: %s process %d terminated normally", 
+                                                                       (cur->type == TYPE_WORKER) ? "worker" : "controller", cur->pid);
                                        }
                                        else {
                                                if (WIFSIGNALED (res)) {
-                                                       msg_warn ("main: worker process %d terminated abnormally by signal: %d", 
+                                                       msg_warn ("main: %s process %d terminated abnormally by signal: %d", 
+                                                                               (cur->type == TYPE_WORKER) ? "worker" : "controller",
                                                                                cur->pid, WTERMSIG(res));
                                                }
                                                else {
-                                                       msg_warn ("main: worker process %d terminated abnormally", cur->pid);
+                                                       msg_warn ("main: %s process %d terminated abnormally", 
+                                                                               (cur->type == TYPE_WORKER) ? "worker" : "controller", cur->pid);
                                                }
                                                /* Fork another worker in replace of dead one */
-                                               fork_worker (rspamd, listen_sock, 0, cur->type);
+                                               delay_fork (cur->type);
                                        }
                                        g_free (cur);
                                }
@@ -400,6 +427,10 @@ main (int argc, char **argv, char **env)
                                active_worker = NULL;
                        }
                }
+               if (got_alarm) {
+                       got_alarm = 0;
+                       fork_delayed (rspamd, listen_sock);
+               }
        }
 
        /* Wait for workers termination */
index 6794d7bb75ddabd1a75b5a9caf704d51c9a78e8e..b217800ad786c7b5acb972ad0551edccdadf1946 100644 (file)
@@ -157,13 +157,14 @@ init_signals (struct sigaction *signals, sig_t sig_handler)
        /* Setting up signal handlers */
        /* SIGUSR1 - reopen config file */
        /* SIGUSR2 - worker is ready for accept */
-       sigemptyset(&signals->sa_mask);
-       sigaddset(&signals->sa_mask, SIGTERM);
-       sigaddset(&signals->sa_mask, SIGINT);
-       sigaddset(&signals->sa_mask, SIGHUP);
-       sigaddset(&signals->sa_mask, SIGCHLD);
-       sigaddset(&signals->sa_mask, SIGUSR1);
-       sigaddset(&signals->sa_mask, SIGUSR2);
+       sigemptyset (&signals->sa_mask);
+       sigaddset (&signals->sa_mask, SIGTERM);
+       sigaddset (&signals->sa_mask, SIGINT);
+       sigaddset (&signals->sa_mask, SIGHUP);
+       sigaddset (&signals->sa_mask, SIGCHLD);
+       sigaddset (&signals->sa_mask, SIGUSR1);
+       sigaddset (&signals->sa_mask, SIGUSR2);
+       sigaddset (&signals->sa_mask, SIGALRM);
 
 
        signals->sa_handler = sig_handler;
@@ -173,6 +174,7 @@ init_signals (struct sigaction *signals, sig_t sig_handler)
        sigaction (SIGCHLD, signals, NULL);
        sigaction (SIGUSR1, signals, NULL);
        sigaction (SIGUSR2, signals, NULL);
+       sigaction (SIGALRM, signals, NULL);
 }
 
 void
@@ -790,9 +792,11 @@ void
 file_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg)
 {
        struct config_file *cfg = (struct config_file *)arg;
-       char tmpbuf[128];
+       char tmpbuf[128], timebuf[32];
        int r;
        struct iovec out[3];
+       time_t now;
+       struct tm *tms;
        
        if (cfg->log_fd == -1) {
                return;
@@ -803,7 +807,10 @@ file_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gcha
        }
 
        if (log_level <= cfg->log_level) {
-               r = snprintf (tmpbuf, sizeof (tmpbuf), "#%d: %d rspamd ", (int)getpid (), (int)time (NULL));
+               now = time (NULL);
+               tms = localtime (&now);
+               strftime (timebuf, sizeof (timebuf), "%b %d %H:%M:%S", tms);
+               r = snprintf (tmpbuf, sizeof (tmpbuf), "#%d: %s rspamd ", (int)getpid (), timebuf);
                out[0].iov_base = tmpbuf;
                out[0].iov_len = r;
                out[1].iov_base = (char *)message;