summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2011-03-23 17:42:33 +0300
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2011-03-23 17:42:33 +0300
commit1d4a64659b490140eae991bcc46ce8d8cdf3ab42 (patch)
tree01e2cc3ced563101eb9bc45cebfc6ca2097cec04
parent689855e2bb5a1c911bab1f71da9aa963a8da62a2 (diff)
downloadrspamd-1d4a64659b490140eae991bcc46ce8d8cdf3ab42.tar.gz
rspamd-1d4a64659b490140eae991bcc46ce8d8cdf3ab42.zip
* Main process now has 'hard termination time' - maximum time between getting termination signal and waiting for workers
-rw-r--r--CMakeLists.txt4
-rw-r--r--config.h.in2
-rw-r--r--src/main.c52
3 files changed, 55 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0abd13d9f..6f50b5677 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -423,6 +423,9 @@ ENDIF(HAVE_SYS_WAIT_H)
IF(HAVE_TIME_H)
LIST(APPEND CMAKE_REQUIRED_INCLUDES time.h)
ENDIF(HAVE_TIME_H)
+IF(HAVE_SYS_TIME_H)
+ LIST(APPEND CMAKE_REQUIRED_INCLUDES sys/time.h)
+ENDIF(HAVE_SYS_TIME_H)
CHECK_FUNCTION_EXISTS(setproctitle HAVE_SETPROCTITLE)
CHECK_FUNCTION_EXISTS(getpagesize HAVE_GETPAGESIZE)
@@ -434,6 +437,7 @@ CHECK_FUNCTION_EXISTS(flock HAVE_FLOCK)
CHECK_FUNCTION_EXISTS(tanhl HAVE_TANHL)
CHECK_FUNCTION_EXISTS(sendfile HAVE_SENDFILE)
CHECK_FUNCTION_EXISTS(mkstemp HAVE_MKSTEMP)
+CHECK_FUNCTION_EXISTS(setitimer HAVE_SETITIMER)
CHECK_FUNCTION_EXISTS(clock_gettime HAVE_CLOCK_GETTIME)
CHECK_SYMBOL_EXISTS(PATH_MAX limits.h HAVE_PATH_MAX)
diff --git a/config.h.in b/config.h.in
index bb8e80a28..902fbdee6 100644
--- a/config.h.in
+++ b/config.h.in
@@ -111,6 +111,8 @@
#cmakedefine HAVE_CLOCK_VIRTUAL 1
#cmakedefine HAVE_CLOCK_PROCESS_CPUTIME_ID 1
+#cmakedefine HAVE_SETITIMER 1
+
#cmakedefine WITHOUT_PERL 1
#cmakedefine WITH_LUA 1
diff --git a/src/main.c b/src/main.c
index 43c0a07e6..64357c264 100644
--- a/src/main.c
+++ b/src/main.c
@@ -51,6 +51,9 @@
/* 2 seconds to fork new process in place of dead one */
#define SOFT_FORK_TIME 2
+/* 10 seconds after getting termination signal to terminate all workers with SIGKILL */
+#define HARD_TERMINATION_TIME 10
+
rspamd_hash_t *counters;
@@ -407,10 +410,29 @@ fork_worker (struct rspamd_main *rspamd, struct worker_conf *cf)
}
static void
+set_alarm (guint seconds)
+{
+#ifdef HAVE_SETITIMER
+ static struct itimerval itv;
+
+ itv.it_interval.tv_sec = 0;
+ itv.it_interval.tv_usec = 0;
+ itv.it_value.tv_sec = seconds;
+ itv.it_value.tv_usec = 0;
+
+ if (setitimer (ITIMER_REAL, &itv, NULL) == -1) {
+ msg_err ("set alarm failed: %s", strerror (errno));
+ }
+#else
+ (void)alarm (seconds);
+#endif
+}
+
+static void
delay_fork (struct worker_conf *cf)
{
workers_pending = g_list_prepend (workers_pending, cf);
- (void)alarm (SOFT_FORK_TIME);
+ set_alarm (SOFT_FORK_TIME);
}
@@ -581,9 +603,22 @@ wait_for_workers (gpointer key, gpointer value, gpointer unused)
struct rspamd_worker *w = value;
gint res = 0;
- waitpid (w->pid, &res, 0);
+ if (got_alarm) {
+ got_alarm = 0;
+ /* Set alarm for hard termination */
+ set_alarm (HARD_TERMINATION_TIME);
+ }
+
+ if (waitpid (w->pid, &res, 0) == -1) {
+ if (errno == EINTR) {
+ msg_info ("terminate worker %P with SIGKILL", w->pid);
+ kill (w->pid, SIGKILL);
+ got_alarm = 1;
+ }
+ }
- msg_debug ("%s process %P terminated", process_to_str (w->type), w->pid);
+ msg_info ("%s process %P terminated %s", process_to_str (w->type), w->pid,
+ got_alarm ? "hardly" : "softly");
g_free (w->cf);
g_free (w);
@@ -1023,6 +1058,17 @@ main (gint argc, gchar **argv, gchar **env)
}
}
+ /* Restore some signals */
+ sigemptyset (&signals.sa_mask);
+ sigaddset (&signals.sa_mask, SIGALRM);
+ sigaddset (&signals.sa_mask, SIGINT);
+ sigaddset (&signals.sa_mask, SIGTERM);
+ sigaction (SIGALRM, &signals, NULL);
+ sigaction (SIGTERM, &signals, NULL);
+ sigaction (SIGINT, &signals, NULL);
+ sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL);
+ /* Set alarm for hard termination */
+ set_alarm (HARD_TERMINATION_TIME);
/* Wait for workers termination */
g_hash_table_foreach_remove (rspamd->workers, wait_for_workers, NULL);