session->wrk->nconns--;
rspamd_inet_address_free(session->from_addr);
- REF_RELEASE(session->cfg);
+ CFG_REF_RELEASE(session->cfg);
if (session->pool) {
msg_debug_session("destroy session %p", session);
session->ctx = ctx;
session->cfg = ctx->cfg;
session->lang_det = ctx->lang_det;
- REF_RETAIN(session->cfg);
+ CFG_REF_RETAIN(session->cfg);
session->from_addr = addr;
session->wrk = worker;
ctx->worker = worker;
ctx->cfg = worker->srv->cfg;
+ CFG_REF_RETAIN(ctx->cfg);
ctx->srv = worker->srv;
ctx->custom_commands = g_hash_table_new(rspamd_strcase_hash,
rspamd_strcase_equal);
g_hash_table_unref(ctx->plugins);
g_hash_table_unref(ctx->custom_commands);
- REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
rspamd_log_close(worker->srv->logger);
rspamd_unset_crash_handler(worker->srv);
ctx->peer_fd = -1;
ctx->worker = worker;
ctx->cfg = worker->srv->cfg;
+ CFG_REF_RETAIN(ctx->cfg);
ctx->resolver = rspamd_dns_resolver_init(worker->srv->logger,
ctx->event_loop,
worker->srv->cfg);
kh_destroy(fuzzy_key_ids_set, ctx->weak_ids);
}
- REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
rspamd_log_close(worker->srv->logger);
rspamd_unset_crash_handler(worker->srv);
g_assert(rspamd_worker_check_context(worker->ctx, rspamd_hs_helper_magic));
ctx->cfg = worker->srv->cfg;
+ CFG_REF_RETAIN(ctx->cfg);
if (ctx->hs_dir == NULL) {
ctx->hs_dir = ctx->cfg->hs_cache_dir;
rspamd_worker_block_signals();
rspamd_log_close(worker->srv->logger);
- REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
rspamd_unset_crash_handler(worker->srv);
exit(EXIT_SUCCESS);
void rspamd_cryptobox_deinit(struct rspamd_cryptobox_library_ctx *ctx)
{
- if (ctx) {
+ if (ctx && cryptobox_loaded) {
g_free(ctx->cpu_extensions);
g_free(ctx);
+ cryptobox_loaded = FALSE;
}
}
RSPAMD_LOG_FUNC, \
__VA_ARGS__)
+/**
+ * Special refcount macros for rspamd_config with logging
+ */
+#define CFG_REF_INIT_RETAIN(cfg, dtor_cb) \
+ do { \
+ if ((cfg) != NULL) { \
+ (cfg)->ref.refcount = 1; \
+ (cfg)->ref.dtor = (ref_dtor_cb_t) (dtor_cb); \
+ rspamd_default_log_function(G_LOG_LEVEL_DEBUG, "config", NULL, \
+ G_STRFUNC, "CFG_REF_INIT_RETAIN %p at %s:%d refcount=1", \
+ (void *) (cfg), __FILE__, __LINE__); \
+ } \
+ } while (0)
+
+#define CFG_REF_RETAIN(cfg) \
+ do { \
+ if ((cfg) != NULL) { \
+ (cfg)->ref.refcount++; \
+ rspamd_default_log_function(G_LOG_LEVEL_DEBUG, "config", NULL, \
+ G_STRFUNC, "CFG_REF_RETAIN %p at %s:%d refcount=%ud", \
+ (void *) (cfg), __FILE__, __LINE__, (cfg)->ref.refcount); \
+ } \
+ } while (0)
+
+#define CFG_REF_RELEASE(cfg) \
+ do { \
+ if ((cfg) != NULL) { \
+ unsigned int _old_rc = (cfg)->ref.refcount; \
+ if (--(cfg)->ref.refcount == 0 && (cfg)->ref.dtor) { \
+ rspamd_default_log_function(G_LOG_LEVEL_DEBUG, "config", NULL, \
+ G_STRFUNC, "CFG_REF_RELEASE %p at %s:%d refcount=%ud->0 DESTROYING", \
+ (void *) (cfg), __FILE__, __LINE__, _old_rc); \
+ (cfg)->ref.dtor(cfg); \
+ } \
+ else { \
+ rspamd_default_log_function(G_LOG_LEVEL_DEBUG, "config", NULL, \
+ G_STRFUNC, "CFG_REF_RELEASE %p at %s:%d refcount=%ud->%ud", \
+ (void *) (cfg), __FILE__, __LINE__, _old_rc, \
+ (cfg)->ref.refcount); \
+ } \
+ } \
+ } while (0)
+
#ifdef __cplusplus
}
#endif
msg_info_config("configuration has been transformed in Lua");
}
- /* error function */
+ /* Clear stack completely */
lua_settop(L, 0);
}
return true;
}
+static void
+rspamd_rcl_jinja_free(unsigned char *data, size_t len, void *user_data)
+{
+ UCL_FREE(len, data);
+}
+
static bool
rspamd_rcl_jinja_handler(struct ucl_parser *parser,
const unsigned char *source, size_t source_len,
jinja_handler->user_data = cfg;
jinja_handler->flags = UCL_SPECIAL_HANDLER_PREPROCESS_ALL;
jinja_handler->handler = rspamd_rcl_jinja_handler;
+ jinja_handler->free_function = rspamd_rcl_jinja_free;
ucl_parser_add_special_handler(parser.get(), jinja_handler);
}
return FALSE;
}
+ /* Free old UCL object if it exists (e.g., after lua_cfg_transform) */
+ if (cfg->cfg_ucl_obj) {
+ ucl_object_unref(cfg->cfg_ucl_obj);
+ }
+ if (cfg->config_comments) {
+ ucl_object_unref(cfg->config_comments);
+ }
+
cfg->cfg_ucl_obj = ucl_parser_get_object(parser.get());
cfg->config_comments = ucl_object_ref(ucl_parser_get_comments(parser.get()));
}
rep.reply.reresolve.status = 0;
- REF_RELEASE(cfg);
+ CFG_REF_RELEASE(cfg);
}
else {
rep.reply.reresolve.status = EINVAL;
if (cfg) {
new_task->cfg = cfg;
- REF_RETAIN(cfg);
+ CFG_REF_RETAIN(cfg);
if (cfg->check_all_filters) {
new_task->flags |= RSPAMD_TASK_FLAG_PASS_ALL;
(double) task->cfg->full_gc_iters / 2);
}
- REF_RELEASE(task->cfg);
+ CFG_REF_RELEASE(task->cfg);
}
kh_destroy(rspamd_req_headers_hash, task->request_headers);
GOptionContext *context;
GError *error = NULL;
const char *confdir;
- struct rspamd_config *cfg = rspamd_main->cfg;
+ struct rspamd_config *cfg;
gboolean ret = TRUE;
worker_t **pworker;
const uint64_t *log_cnt;
+ cfg = rspamd_config_new(RSPAMD_CONFIG_INIT_DEFAULT | RSPAMD_CONFIG_INIT_WIPE_LUA_MEM);
+ cfg->libs_ctx = rspamd_init_libs();
context = g_option_context_new(
"configtest - perform configuration file test");
g_option_context_set_summary(context,
/* Do post-load actions */
rspamd_lua_post_load_config(cfg);
- if (!rspamd_init_filters(rspamd_main->cfg, false, strict)) {
+ if (!rspamd_init_filters(cfg, false, strict)) {
ret = FALSE;
}
rspamd_printf("syntax %s\n", ret ? "OK" : "BAD");
}
+ CFG_REF_RELEASE(cfg);
if (!ret) {
exit(EXIT_FAILURE);
}
rspamd_session_destroy(rspamadm_session);
g_option_context_free(context);
rspamd_dns_resolver_deinit(resolver);
- REF_RELEASE(rspamd_main->cfg);
+ CFG_REF_RELEASE(rspamd_main->cfg);
rspamd_http_context_free(rspamd_main->http_ctx);
rspamd_log_close(rspamd_main->logger);
rspamd_url_deinit();
g_assert(rspamd_worker_check_context(worker->ctx, rspamd_rspamd_proxy_magic));
ctx->cfg = worker->srv->cfg;
+ CFG_REF_RETAIN(ctx->cfg);
ctx->srv = worker->srv;
ctx->event_loop = rspamd_prepare_worker(worker, "rspamd_proxy",
proxy_accept_socket);
rspamd_controller_on_terminate(worker, NULL);
}
- REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
rspamd_log_close(worker->srv->logger);
rspamd_unset_crash_handler(worker->srv);
g_assert(rspamd_worker_check_context(worker->ctx, rspamd_worker_magic));
ctx->cfg = worker->srv->cfg;
+ CFG_REF_RETAIN(ctx->cfg);
ctx->event_loop = rspamd_prepare_worker(worker, "normal", accept_socket);
rspamd_symcache_start_refresh(worker->srv->cfg->cache, ctx->event_loop,
worker);
}
rspamd_stat_close();
- REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
+ CFG_REF_RELEASE(ctx->cfg);
rspamd_log_close(worker->srv->logger);
rspamd_unset_crash_handler(worker->srv);
g_assert(rspamd_upstreams_alive(ls) == 3);
rspamd_upstreams_destroy(ls);
- REF_RELEASE(cfg);
+ CFG_REF_RELEASE(cfg);
}