]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Do not leave parent-less workers processes on fatal errors
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 20 Jan 2017 12:38:45 +0000 (12:38 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 20 Jan 2017 12:39:09 +0000 (12:39 +0000)
src/libserver/worker_util.c
src/libserver/worker_util.h
src/rspamd.c

index d113acc1f571c5517d3d2caade2684b114a8a2c1..ac87f2870a628d3e041ed645d0d7deafde8e2d74 100644 (file)
@@ -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);
+}
index 2ad312b0ef28623a8dcbf6cc48edb6ff0a79e7b2..634ffe67b9cc0f0c2822ddd3dbaabf7a0e72d469 100644 (file)
@@ -123,6 +123,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
  */
index 877ac00a5f38cdab2cf2ffe2a415f90df20ebd3d..44931dfdabfaf3b5daed71aa5dbc2f34d6ce0838 100644 (file)
@@ -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 {