aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-10-09 17:16:01 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-10-09 17:16:01 +0100
commitf1a8608981442bda6ffccafc8f1e6f72dc556ff4 (patch)
treeda463e23e839e4d17f0eacc9001e276a8caf8c9e
parent6b78dbc9e9f0ffda46c173178504db823516b2b4 (diff)
downloadrspamd-f1a8608981442bda6ffccafc8f1e6f72dc556ff4.tar.gz
rspamd-f1a8608981442bda6ffccafc8f1e6f72dc556ff4.zip
Move forking of worker to worker_util.
-rw-r--r--src/libserver/worker_util.c133
-rw-r--r--src/libserver/worker_util.h23
2 files changed, 156 insertions, 0 deletions
diff --git a/src/libserver/worker_util.c b/src/libserver/worker_util.c
index c9e0521d2..ea3125ac8 100644
--- a/src/libserver/worker_util.c
+++ b/src/libserver/worker_util.c
@@ -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;
+}
diff --git a/src/libserver/worker_util.h b/src/libserver/worker_util.h
index f919b0554..30fbe904f 100644
--- a/src/libserver/worker_util.h
+++ b/src/libserver/worker_util.h
@@ -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_ */