From f7639eb2dc2373dd4a47eb93efed0646c4a41fb5 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 11 Jan 2009 12:39:37 +0300 Subject: [PATCH] * Implement delayed fork of dead workers (to avoid fork bombs) * Implement refork of controller * Log time to console in normal view --- src/main.c | 53 ++++++++++++++++++++++++++++++++++++++++++----------- src/util.c | 25 ++++++++++++++++--------- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/main.c b/src/main.c index e2649e911..454f164ea 100644 --- a/src/main.c +++ b/src/main.c @@ -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 */ diff --git a/src/util.c b/src/util.c index 6794d7bb7..b217800ad 100644 --- a/src/util.c +++ b/src/util.c @@ -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; -- 2.39.5