summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-01-20 12:38:45 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-01-20 12:39:09 +0000
commit86f76528fa2b3c3603c649835bbc4d0a21ed0a4d (patch)
treecf0606bf90fd4689af317f03ee85fc7e49a0c04b /src
parent08a441f3b5b1ee1ba02a999a552e54725ad1138a (diff)
downloadrspamd-86f76528fa2b3c3603c649835bbc4d0a21ed0a4d.tar.gz
rspamd-86f76528fa2b3c3603c649835bbc4d0a21ed0a4d.zip
[Fix] Do not leave parent-less workers processes on fatal errors
Diffstat (limited to 'src')
-rw-r--r--src/libserver/worker_util.c41
-rw-r--r--src/libserver/worker_util.h6
-rw-r--r--src/rspamd.c4
3 files changed, 47 insertions, 4 deletions
diff --git a/src/libserver/worker_util.c b/src/libserver/worker_util.c
index d113acc1f..ac87f2870 100644
--- a/src/libserver/worker_util.c
+++ b/src/libserver/worker_util.c
@@ -530,12 +530,12 @@ rspamd_fork_worker (struct rspamd_main *rspamd_main,
if (!rspamd_socketpair (wrk->control_pipe)) {
msg_err ("socketpair failure: %s", strerror (errno));
- exit (-errno);
+ rspamd_hard_terminate (rspamd_main);
}
if (!rspamd_socketpair (wrk->srv_pipe)) {
msg_err ("socketpair failure: %s", strerror (errno));
- exit (-errno);
+ rspamd_hard_terminate (rspamd_main);
}
wrk->srv = rspamd_main;
@@ -610,7 +610,7 @@ rspamd_fork_worker (struct rspamd_main *rspamd_main,
case -1:
msg_err_main ("cannot fork main process. %s", strerror (errno));
rspamd_pidfile_remove (rspamd_main->pfh);
- exit (-errno);
+ rspamd_hard_terminate (rspamd_main);
break;
default:
/* Close worker part of socketpair */
@@ -641,3 +641,38 @@ rspamd_worker_block_signals (void)
sigaddset (&set, SIGUSR2);
sigprocmask (SIG_BLOCK, &set, NULL);
}
+
+void
+rspamd_hard_terminate (struct rspamd_main *rspamd_main)
+{
+ GHashTableIter it;
+ gpointer k, v;
+ struct rspamd_worker *w;
+ sigset_t set;
+
+ /* Block all signals */
+ sigemptyset (&set);
+ sigaddset (&set, SIGTERM);
+ sigaddset (&set, SIGINT);
+ sigaddset (&set, SIGHUP);
+ sigaddset (&set, SIGUSR1);
+ sigaddset (&set, SIGUSR2);
+ sigaddset (&set, SIGCHLD);
+ sigprocmask (SIG_BLOCK, &set, NULL);
+
+ /* We need to terminate all workers that might be already spawned */
+ rspamd_worker_block_signals ();
+ g_hash_table_iter_init (&it, rspamd_main->workers);
+
+ while (g_hash_table_iter_next (&it, &k, &v)) {
+ w = v;
+ msg_err_main ("kill worker %p as Rspamd is terminating due to "
+ "an unrecoverable error", w->pid);
+ kill (w->pid, SIGKILL);
+ }
+
+ msg_err_main ("shutting down Rspamd due to fatal error");
+
+ rspamd_log_close (rspamd_main->logger);
+ exit (EXIT_FAILURE);
+}
diff --git a/src/libserver/worker_util.h b/src/libserver/worker_util.h
index 2ad312b0e..634ffe67b 100644
--- a/src/libserver/worker_util.h
+++ b/src/libserver/worker_util.h
@@ -124,6 +124,12 @@ void rspamd_worker_stop_accept (struct rspamd_worker *worker);
void rspamd_worker_block_signals (void);
/**
+ * Kill rspamd main and all workers
+ * @param rspamd_main
+ */
+void rspamd_hard_terminate (struct rspamd_main *rspamd_main) G_GNUC_NORETURN;
+
+/**
* Fork new worker with the specified configuration
*/
struct rspamd_worker *rspamd_fork_worker (struct rspamd_main *,
diff --git a/src/rspamd.c b/src/rspamd.c
index 877ac00a5..44931dfda 100644
--- a/src/rspamd.c
+++ b/src/rspamd.c
@@ -588,6 +588,7 @@ spawn_workers (struct rspamd_main *rspamd_main, struct event_base *ev_base)
cf->listen_socks = g_list_concat (cf->listen_socks, ls);
}
}
+
if (listen_ok) {
spawn_worker_type (rspamd_main, ev_base, cf);
}
@@ -595,7 +596,8 @@ spawn_workers (struct rspamd_main *rspamd_main, struct event_base *ev_base)
msg_err_main ("cannot create listen socket for %s at %s",
g_quark_to_string (cf->type), cf->bind_conf->name);
- exit (EXIT_FAILURE);
+ rspamd_hard_terminate (rspamd_main);
+ g_assert_not_reached ();
}
}
else {