aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2009-01-11 12:39:37 +0300
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2009-01-11 12:39:37 +0300
commitf7639eb2dc2373dd4a47eb93efed0646c4a41fb5 (patch)
tree74ebedee200446c7caec1dbf4c0092129016f895 /src
parent5f0da61541dd368961694b26766b12d051227844 (diff)
downloadrspamd-f7639eb2dc2373dd4a47eb93efed0646c4a41fb5.tar.gz
rspamd-f7639eb2dc2373dd4a47eb93efed0646c4a41fb5.zip
* Implement delayed fork of dead workers (to avoid fork bombs)
* Implement refork of controller * Log time to console in normal view
Diffstat (limited to 'src')
-rw-r--r--src/main.c53
-rw-r--r--src/util.c25
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;