]> source.dussan.org Git - rspamd.git/commitdiff
Move forking of worker to worker_util.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 9 Oct 2015 16:16:01 +0000 (17:16 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 9 Oct 2015 16:16:01 +0000 (17:16 +0100)
src/libserver/worker_util.c
src/libserver/worker_util.h

index c9e0521d25dae70b96f08d81dd18ef8fbdb5c3ce..ea3125ac851e5f21a38994348e36754ae3af2125 100644 (file)
@@ -28,6 +28,7 @@
 #include "worker_util.h"
 #include "unix-std.h"
 #include "utlist.h"
+#include "ottery.h"
 
 #ifdef WITH_GPERF_TOOLS
 #include <google/profiler.h>
@@ -362,3 +363,135 @@ rspamd_controller_send_ucl (struct rspamd_http_connection_entry *entry,
                entry->rt->ev_base);
        entry->is_reply = TRUE;
 }
+
+static void
+rspamd_worker_drop_priv (struct rspamd_main *rspamd_main)
+{
+       if (rspamd_main->is_privilleged) {
+               if (setgid (rspamd_main->workers_gid) == -1) {
+                       msg_err_main ("cannot setgid to %d (%s), aborting",
+                                       (gint) rspamd_main->workers_gid,
+                                       strerror (errno));
+                       exit (-errno);
+               }
+               if (rspamd_main->cfg->rspamd_user &&
+                               initgroups (rspamd_main->cfg->rspamd_user, rspamd_main->workers_gid) ==
+                                               -1) {
+                       msg_err_main ("initgroups failed (%s), aborting", strerror (errno));
+                       exit (-errno);
+               }
+               if (setuid (rspamd_main->workers_uid) == -1) {
+                       msg_err_main ("cannot setuid to %d (%s), aborting",
+                                       (gint) rspamd_main->workers_uid,
+                                       strerror (errno));
+                       exit (-errno);
+               }
+       }
+}
+
+static void
+rspamd_worker_set_limits (struct rspamd_main *rspamd_main,
+               struct rspamd_worker_conf *cf)
+{
+       struct rlimit rlmt;
+
+       if (cf->rlimit_nofile != 0) {
+               rlmt.rlim_cur = (rlim_t) cf->rlimit_nofile;
+               rlmt.rlim_max = (rlim_t) cf->rlimit_nofile;
+
+               if (setrlimit (RLIMIT_NOFILE, &rlmt) == -1) {
+                       msg_warn_main ("cannot set files rlimit: %d, %s",
+                                       cf->rlimit_nofile,
+                                       strerror (errno));
+               }
+       }
+
+       if (cf->rlimit_maxcore != 0) {
+               rlmt.rlim_cur = (rlim_t) cf->rlimit_maxcore;
+               rlmt.rlim_max = (rlim_t) cf->rlimit_maxcore;
+
+               if (setrlimit (RLIMIT_CORE, &rlmt) == -1) {
+                       msg_warn_main ("cannot set max core rlimit: %d, %s",
+                                       cf->rlimit_maxcore,
+                                       strerror (errno));
+               }
+       }
+}
+
+struct rspamd_worker *
+rspamd_fork_worker (struct rspamd_main *rspamd_main,
+               struct rspamd_worker_conf *cf,
+               guint index)
+{
+       struct rspamd_worker *cur;
+       /* Starting worker process */
+       cur = (struct rspamd_worker *) g_malloc0 (sizeof (struct rspamd_worker));
+
+       if (!rspamd_socketpair (cur->control_pipe)) {
+               msg_err ("socketpair failure: %s", strerror (errno));
+               exit (-errno);
+       }
+
+       cur->srv = rspamd_main;
+       cur->type = cf->type;
+       cur->cf = g_malloc (sizeof (struct rspamd_worker_conf));
+       memcpy (cur->cf, cf, sizeof (struct rspamd_worker_conf));
+       cur->index = index;
+       cur->ctx = cf->ctx;
+
+       cur->pid = fork ();
+
+       switch (cur->pid) {
+       case 0:
+               /* Update pid for logging */
+               rspamd_log_update_pid (cf->type, rspamd_main->logger);
+               /* Lock statfile pool if possible XXX */
+               /* Init PRNG after fork */
+               ottery_init (NULL);
+               g_random_set_seed (ottery_rand_uint32 ());
+               /* Drop privilleges */
+               rspamd_worker_drop_priv (rspamd_main);
+               /* Set limits */
+               rspamd_worker_set_limits (rspamd_main, cf);
+               setproctitle ("%s process", cf->worker->name);
+               rspamd_pidfile_close (rspamd_main->pfh);
+               /* Do silent log reopen to avoid collisions */
+               rspamd_log_close (rspamd_main->logger);
+               rspamd_log_open (rspamd_main->logger);
+
+#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30))
+# if (GLIB_MINOR_VERSION > 20)
+               /* Ugly hack for old glib */
+               if (!g_thread_get_initialized ()) {
+                       g_thread_init (NULL);
+               }
+# else
+               g_thread_init (NULL);
+# endif
+#endif
+               msg_info_main ("starting %s process %P", cf->worker->name, getpid ());
+               /* Close parent part of socketpair */
+               close (cur->control_pipe[0]);
+               /* Set non-blocking on the worker part of socketpair */
+               rspamd_socket_nonblocking (cur->control_pipe[1]);
+               /* Execute worker */
+               cf->worker->worker_start_func (cur);
+               break;
+       case -1:
+               msg_err_main ("cannot fork main process. %s", strerror (errno));
+               rspamd_pidfile_remove (rspamd_main->pfh);
+               exit (-errno);
+               break;
+       default:
+               /* Close worker part of socketpair */
+               close (cur->control_pipe[1]);
+               /* Set blocking on the main part of socketpair */
+               rspamd_socket_nonblocking (cur->control_pipe[0]);
+               /* Insert worker into worker's table, pid is index */
+               g_hash_table_insert (rspamd_main->workers, GSIZE_TO_POINTER (
+                               cur->pid), cur);
+               break;
+       }
+
+       return cur;
+}
index f919b0554caeac13a97fca35e6ce38888299d804..30fbe904f357ad015770ecbee91366cd05c983ba 100644 (file)
@@ -111,4 +111,27 @@ worker_t * rspamd_get_worker_by_type (struct rspamd_config *cfg, GQuark type);
 
 void rspamd_worker_stop_accept (struct rspamd_worker *worker);
 
+/**
+ * Fork new worker with the specified configuration
+ */
+struct rspamd_worker *rspamd_fork_worker (struct rspamd_main *,
+               struct rspamd_worker_conf *, guint);
+
+#define msg_err_main(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
+        rspamd_main->server_pool->tag.tagname, rspamd_main->server_pool->tag.uid, \
+        G_STRFUNC, \
+        __VA_ARGS__)
+#define msg_warn_main(...)   rspamd_default_log_function (G_LOG_LEVEL_WARNING, \
+        rspamd_main->server_pool->tag.tagname, rspamd_main->server_pool->tag.uid, \
+        G_STRFUNC, \
+        __VA_ARGS__)
+#define msg_info_main(...)   rspamd_default_log_function (G_LOG_LEVEL_INFO, \
+        rspamd_main->server_pool->tag.tagname, rspamd_main->server_pool->tag.uid, \
+        G_STRFUNC, \
+        __VA_ARGS__)
+#define msg_debug_main(...)  rspamd_default_log_function (G_LOG_LEVEL_DEBUG, \
+        rspamd_main->server_pool->tag.tagname, rspamd_main->server_pool->tag.uid, \
+        G_STRFUNC, \
+        __VA_ARGS__)
+
 #endif /* WORKER_UTIL_H_ */