From b33f3fa4cfa42f1b92192ff18eb893b8bd93a1e9 Mon Sep 17 00:00:00 2001
From: Vsevolod Stakhov <vsevolod@highsecure.ru>
Date: Wed, 18 Nov 2015 14:48:01 +0000
Subject: Start refcounting rework for rspamd_config

---
 src/libcryptobox/cryptobox.c |  7 +++++
 src/libserver/cfg_file.h     | 17 +++++-------
 src/libserver/cfg_utils.c    | 43 ++++++++++++++++++------------
 src/libutil/util.c           |  9 ++++++-
 src/rspamd.c                 | 63 ++++++++++++--------------------------------
 src/rspamd.h                 |  1 +
 6 files changed, 65 insertions(+), 75 deletions(-)

(limited to 'src')

diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c
index 0b9e5ad04..038c94adb 100644
--- a/src/libcryptobox/cryptobox.c
+++ b/src/libcryptobox/cryptobox.c
@@ -62,6 +62,7 @@
 unsigned long cpu_config = 0;
 
 static gboolean use_openssl = FALSE;
+static gboolean cryptobox_loaded = FALSE;
 
 static const guchar n0[16] = {0};
 
@@ -186,6 +187,12 @@ rspamd_cryptobox_init (void)
 {
 	gint cpu[4], nid;
 
+	if (cryptobox_loaded) {
+		/* Ignore reload attempts */
+		return;
+	}
+
+	cryptobox_loaded = TRUE;
 	rspamd_cryptobox_cpuid (cpu, 0);
 	nid = cpu[0];
 	rspamd_cryptobox_cpuid (cpu, 1);
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index c70ecddae..a2ec19034 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -13,6 +13,7 @@
 #include "cfg_rcl.h"
 #include "ucl.h"
 #include "regexp.h"
+#include "ref.h"
 
 #define DEFAULT_BIND_PORT 11333
 #define DEFAULT_CONTROL_PORT 11334
@@ -219,8 +220,6 @@ struct rspamd_config {
 	gchar *profile_path;
 #endif
 
-	gboolean no_fork;                               /**< if 1 do not call daemon()							*/
-	gboolean config_test;                           /**< if TRUE do only config file test					*/
 	gboolean raw_mode;                              /**< work in raw mode instead of utf one				*/
 	gboolean one_shot_mode;                         /**< rules add only one symbol							*/
 	gboolean check_text_attachements;               /**< check text attachements as text					*/
@@ -323,6 +322,8 @@ struct rspamd_config {
 	gchar *log_format_str;							/**< raw log format string								*/
 
 	struct rspamd_external_libs_ctx *libs_ctx;		/**< context for external libraries						*/
+
+	ref_entry_t ref;								/**< reference counter									*/
 };
 
 
@@ -340,7 +341,7 @@ gboolean rspamd_parse_bind_line (struct rspamd_config *cfg,
  * Init default values
  * @param cfg config file
  */
-void rspamd_config_defaults (struct rspamd_config *cfg);
+struct rspamd_config * rspamd_config_defaults (void);
 
 /**
  * Free memory used by config structure
@@ -371,7 +372,8 @@ gchar rspamd_config_parse_flag (const gchar *str, guint len);
  * Do post load actions for config
  * @param cfg config file
  */
-void rspamd_config_post_load (struct rspamd_config *cfg);
+gboolean rspamd_config_post_load (struct rspamd_config *cfg,
+		gboolean validate_cache);
 
 /**
  * Calculate checksum for config file
@@ -460,13 +462,6 @@ void rspamd_ucl_add_conf_variables (struct ucl_parser *parser, GHashTable *vars)
  */
 gboolean rspamd_init_filters (struct rspamd_config *cfg, bool reconfig);
 
-/**
- * Init configuration file structure
- * @param cfg
- * @param init_lua
- */
-void rspamd_init_cfg (struct rspamd_config *cfg, gboolean init_lua);
-
 /**
  * Add new symbol to the metric
  * @param metric metric's name (or NULL for the default metric)
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index b85534dd7..5d0eb06ae 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -144,9 +144,13 @@ rspamd_parse_bind_line (struct rspamd_config *cfg,
 	return ret;
 }
 
-void
-rspamd_config_defaults (struct rspamd_config *cfg)
+struct rspamd_config *
+rspamd_config_defaults (void)
 {
+	struct rspamd_config *cfg;
+
+	cfg = g_slice_alloc0 (sizeof (*cfg));
+	cfg->cfg_pool = rspamd_mempool_new (rspamd_mempool_suggest_size (), "cfg");
 	cfg->dns_timeout = 1000;
 	cfg->dns_retransmits = 5;
 	/* After 20 errors do throttling for 10 seconds */
@@ -190,6 +194,11 @@ rspamd_config_defaults (struct rspamd_config *cfg)
 	cfg->words_decay = DEFAULT_WORDS_DECAY;
 	cfg->min_word_len = DEFAULT_MIN_WORD;
 	cfg->max_word_len = DEFAULT_MAX_WORD;
+
+	cfg->lua_state = rspamd_lua_init (cfg);
+	cfg->cache = rspamd_symbols_cache_new (cfg);
+
+	REF_INIT_RETAIN (cfg, rspamd_config_free);
 }
 
 void
@@ -215,6 +224,9 @@ rspamd_config_free (struct rspamd_config *cfg)
 
 	g_list_free (cfg->classifiers);
 	g_list_free (cfg->metrics_list);
+	lua_close (cfg->lua_state);
+	rspamd_symbols_cache_destroy (cfg->cache);
+	REF_RELEASE (cfg->libs_ctx);
 	rspamd_mempool_delete (cfg->cfg_pool);
 }
 
@@ -578,8 +590,8 @@ rspamd_config_parse_log_format (struct rspamd_config *cfg)
 /*
  * Perform post load actions
  */
-void
-rspamd_config_post_load (struct rspamd_config *cfg)
+gboolean
+rspamd_config_post_load (struct rspamd_config *cfg, gboolean validate_cache)
 {
 #ifdef HAVE_CLOCK_GETTIME
 	struct timespec ts;
@@ -649,6 +661,16 @@ rspamd_config_post_load (struct rspamd_config *cfg)
 	if (!rspamd_config_parse_log_format (cfg)) {
 		msg_err_config ("cannot parse log format, task logging will not be available");
 	}
+
+	/* Init config cache */
+	rspamd_symbols_cache_init (cfg->cache);
+
+	/* Validate cache */
+	if (validate_cache) {
+		return rspamd_symbols_cache_validate (cfg->cache, cfg, FALSE);
+	}
+
+	return TRUE;
 }
 
 #if 0
@@ -1180,19 +1202,6 @@ rspamd_init_filters (struct rspamd_config *cfg, bool reconfig)
 	return rspamd_init_lua_filters (cfg);
 }
 
-void
-rspamd_init_cfg (struct rspamd_config *cfg, gboolean init_lua)
-{
-	cfg->cfg_pool = rspamd_mempool_new (rspamd_mempool_suggest_size (), "cfg");
-	rspamd_config_defaults (cfg);
-
-	if (init_lua) {
-		cfg->lua_state = rspamd_lua_init (cfg);
-		rspamd_mempool_add_destructor (cfg->cfg_pool,
-				(rspamd_mempool_destruct_t)lua_close, cfg->lua_state);
-	}
-}
-
 gboolean
 rspamd_config_add_metric_symbol (struct rspamd_config *cfg,
 		const gchar *metric_name, const gchar *symbol,
diff --git a/src/libutil/util.c b/src/libutil/util.c
index 286ec5091..8afac64c0 100644
--- a/src/libutil/util.c
+++ b/src/libutil/util.c
@@ -1961,7 +1961,6 @@ rspamd_init_libs (void)
 	rlim.rlim_cur = 100 * 1024 * 1024;
 	setrlimit (RLIMIT_STACK, &rlim);
 
-	event_init ();
 #ifdef GMIME_ENABLE_RFC2047_WORKAROUNDS
 	g_mime_init (GMIME_ENABLE_RFC2047_WORKAROUNDS);
 #else
@@ -1970,6 +1969,7 @@ rspamd_init_libs (void)
 	ctx->libmagic = magic_open (MAGIC_MIME|MAGIC_NO_CHECK_COMPRESS|
 			MAGIC_NO_CHECK_ELF|MAGIC_NO_CHECK_TAR);
 	magic_compile (ctx->libmagic, NULL);
+	REF_INIT_RETAIN (ctx, rspamd_deinit_libs);
 
 	return ctx;
 }
@@ -1983,6 +1983,13 @@ rspamd_deinit_libs (struct rspamd_external_libs_ctx *ctx)
 		}
 
 		g_slice_free1 (sizeof (*ctx), ctx);
+
+		g_mime_shutdown ();
+
+#ifdef HAVE_OPENSSL
+		EVP_cleanup ();
+		ERR_free_strings ();
+#endif
 	}
 }
 
diff --git a/src/rspamd.c b/src/rspamd.c
index c816b455a..3d42f2650 100644
--- a/src/rspamd.c
+++ b/src/rspamd.c
@@ -73,7 +73,8 @@
 
 static gboolean load_rspamd_config (struct rspamd_main *rspamd_main,
 		struct rspamd_config *cfg,
-		gboolean init_modules);
+		gboolean init_modules,
+		gboolean validate);
 
 /* Control socket */
 static gint control_fd;
@@ -160,8 +161,6 @@ read_cmd_line (gint *argc, gchar ***argv, struct rspamd_config *cfg)
 		exit (1);
 	}
 
-	cfg->no_fork = no_fork;
-	cfg->config_test = config_test;
 	cfg->rspamd_user = rspamd_user;
 	cfg->rspamd_group = rspamd_group;
 	cfg_num = cfg_names != NULL ? g_strv_length (cfg_names) : 0;
@@ -269,28 +268,24 @@ reread_config (struct rspamd_main *rspamd_main)
 	struct rspamd_config *tmp_cfg;
 	gchar *cfg_file;
 
-	tmp_cfg = (struct rspamd_config *)g_malloc0 (sizeof (struct rspamd_config));
+	tmp_cfg = rspamd_config_defaults ();
 	tmp_cfg->c_modules = g_hash_table_ref (rspamd_main->cfg->c_modules);
-	tmp_cfg->libs_ctx = rspamd_main->cfg->libs_ctx;
+	tmp_cfg->libs_ctx = REF_RETAIN (rspamd_main->cfg->libs_ctx);
 	rspamd_set_logger (tmp_cfg,  g_quark_try_string ("main"), rspamd_main);
-	rspamd_init_cfg (tmp_cfg, TRUE);
 	cfg_file = rspamd_mempool_strdup (tmp_cfg->cfg_pool,
 			rspamd_main->cfg->cfg_name);
-	tmp_cfg->cache = rspamd_symbols_cache_new (tmp_cfg);
 	/* Save some variables */
 	tmp_cfg->cfg_name = cfg_file;
 
-	if (!load_rspamd_config (rspamd_main, tmp_cfg, FALSE)) {
+	if (!load_rspamd_config (rspamd_main, tmp_cfg, FALSE, TRUE)) {
 		rspamd_set_logger (rspamd_main->cfg, g_quark_try_string (
 				"main"), rspamd_main);
 		msg_err_main ("cannot parse new config file, revert to old one");
-		rspamd_config_free (tmp_cfg);
+		REF_RELEASE (tmp_cfg);
 	}
 	else {
 		msg_debug_main ("replacing config");
-		rspamd_symbols_cache_destroy (rspamd_main->cfg->cache);
-		rspamd_config_free (rspamd_main->cfg);
-		g_free (rspamd_main->cfg);
+		REF_RELEASE (rspamd_main->cfg);
 
 		rspamd_main->cfg = tmp_cfg;
 		rspamd_set_logger (tmp_cfg,  g_quark_try_string ("main"), rspamd_main);
@@ -300,7 +295,6 @@ reread_config (struct rspamd_main *rspamd_main)
 		}
 
 		rspamd_init_filters (rspamd_main->cfg, TRUE);
-		rspamd_symbols_cache_init (rspamd_main->cfg->cache);
 		msg_info_main ("config has been reread successfully");
 	}
 }
@@ -579,9 +573,8 @@ reopen_log_handler (gpointer key, gpointer value, gpointer unused)
 
 static gboolean
 load_rspamd_config (struct rspamd_main *rspamd_main,
-		struct rspamd_config *cfg, gboolean init_modules)
+		struct rspamd_config *cfg, gboolean init_modules, gboolean validate)
 {
-	cfg->cache = rspamd_symbols_cache_new (cfg);
 	cfg->compiled_modules = modules;
 	cfg->compiled_workers = workers;
 
@@ -603,7 +596,7 @@ load_rspamd_config (struct rspamd_main *rspamd_main,
 	}
 
 	/* Do post-load actions */
-	rspamd_config_post_load (cfg);
+	rspamd_config_post_load (cfg, validate);
 
 	if (init_modules) {
 		rspamd_init_filters (cfg, FALSE);
@@ -811,15 +804,13 @@ main (gint argc, gchar **argv, gchar **env)
 			"main");
 	rspamd_main->stat = rspamd_mempool_alloc0_shared (rspamd_main->server_pool,
 			sizeof (struct rspamd_stat));
-	rspamd_main->cfg =
-			(struct rspamd_config *) g_malloc0 (sizeof (struct rspamd_config));
+	rspamd_main->cfg = rspamd_config_defaults ();
 
 #ifndef HAVE_SETPROCTITLE
 	init_title (argc, argv, env);
 #endif
 
 	rspamd_main->cfg->libs_ctx = rspamd_init_libs ();
-	rspamd_init_cfg (rspamd_main->cfg, TRUE);
 
 	memset (&signals, 0, sizeof (struct sigaction));
 
@@ -848,7 +839,7 @@ main (gint argc, gchar **argv, gchar **env)
 		}
 	}
 
-	if (rspamd_main->cfg->config_test || is_debug) {
+	if (config_test || is_debug) {
 		rspamd_main->cfg->log_level = G_LOG_LEVEL_DEBUG;
 	}
 	else {
@@ -897,22 +888,17 @@ main (gint argc, gchar **argv, gchar **env)
 		exit (EXIT_SUCCESS);
 	}
 
-	if (rspamd_main->cfg->config_test || dump_cache) {
-		if (!load_rspamd_config (rspamd_main, rspamd_main->cfg, FALSE)) {
+	if (config_test || dump_cache) {
+		if (!load_rspamd_config (rspamd_main, rspamd_main->cfg, FALSE, FALSE)) {
 			exit (EXIT_FAILURE);
 		}
 
 		res = TRUE;
 
-		rspamd_symbols_cache_init (rspamd_main->cfg->cache);
-
 		if (!rspamd_init_filters (rspamd_main->cfg, FALSE)) {
 			res = FALSE;
 		}
 
-		/* Insert classifiers symbols */
-		rspamd_config_insert_classify_symbols (rspamd_main->cfg);
-
 		if (!rspamd_symbols_cache_validate (rspamd_main->cfg->cache,
 				rspamd_main->cfg,
 				FALSE)) {
@@ -929,7 +915,7 @@ main (gint argc, gchar **argv, gchar **env)
 	}
 
 	/* Load config */
-	if (!load_rspamd_config (rspamd_main, rspamd_main->cfg, TRUE)) {
+	if (!load_rspamd_config (rspamd_main, rspamd_main->cfg, TRUE, TRUE)) {
 		exit (EXIT_FAILURE);
 	}
 
@@ -958,8 +944,8 @@ main (gint argc, gchar **argv, gchar **env)
 			rspamd_main->cfg->cfg_name);
 
 	/* Daemonize */
-	if (!rspamd_main->cfg->no_fork && daemon (0, 0) == -1) {
-		fprintf (stderr, "Cannot daemonize\n");
+	if (!no_fork && daemon (0, 0) == -1) {
+		rspamd_fprintf (stderr, "Cannot daemonize\n");
 		exit (-errno);
 	}
 
@@ -988,13 +974,6 @@ main (gint argc, gchar **argv, gchar **env)
 	/* Set title */
 	setproctitle ("main process");
 
-	/* Init config cache */
-	rspamd_symbols_cache_init (rspamd_main->cfg->cache);
-
-	/* Validate cache */
-	(void) rspamd_symbols_cache_validate (rspamd_main->cfg->cache,
-			rspamd_main->cfg,
-			FALSE);
 
 	/* Flush log */
 	rspamd_log_flush (rspamd_main->logger);
@@ -1112,17 +1091,9 @@ main (gint argc, gchar **argv, gchar **env)
 
 	rspamd_symbols_cache_destroy (rspamd_main->cfg->cache);
 	rspamd_log_close (rspamd_main->logger);
-	rspamd_config_free (rspamd_main->cfg);
-	rspamd_deinit_libs (rspamd_main->cfg->libs_ctx);
-	g_free (rspamd_main->cfg);
+	REF_RELEASE (rspamd_main->cfg);
 	g_free (rspamd_main);
 	event_base_free (ev_base);
-	g_mime_shutdown ();
-
-#ifdef HAVE_OPENSSL
-	EVP_cleanup ();
-	ERR_free_strings ();
-#endif
 
 	return (res);
 }
diff --git a/src/rspamd.h b/src/rspamd.h
index 701efb9f8..fece7b98b 100644
--- a/src/rspamd.h
+++ b/src/rspamd.h
@@ -232,6 +232,7 @@ struct controller_session {
 
 struct rspamd_external_libs_ctx {
 	magic_t libmagic;
+	ref_entry_t ref;
 };
 
 
-- 
cgit v1.2.3