From: Vsevolod Stakhov Date: Wed, 23 Mar 2011 14:42:33 +0000 (+0300) Subject: * Main process now has 'hard termination time' - maximum time between getting termina... X-Git-Tag: 0.3.10~3 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=1d4a64659b490140eae991bcc46ce8d8cdf3ab42;p=rspamd.git * Main process now has 'hard termination time' - maximum time between getting termination signal and waiting for workers --- 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; @@ -406,11 +409,30 @@ fork_worker (struct rspamd_main *rspamd, struct worker_conf *cf) return cur; } +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);