From a99900534bc477b40a16cde38d3fe799c11c5ed1 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 11 Dec 2015 17:35:58 +0000 Subject: [PATCH] Enable core files limits for rspamd --- config.h.in | 1 + src/libserver/worker_util.c | 22 +++++++-- src/rspamd.c | 97 +++++++++++++++++++++++++++++++++++++ src/rspamd.h | 1 + 4 files changed, 116 insertions(+), 5 deletions(-) diff --git a/config.h.in b/config.h.in index 6615deadf..908278013 100644 --- a/config.h.in +++ b/config.h.in @@ -52,6 +52,7 @@ #cmakedefine HAVE_NANOSLEEP 1 #cmakedefine HAVE_NETDB_H 1 #cmakedefine HAVE_NETINET_IN_H 1 +#cmakedefine HAVE_NFTW 1 #cmakedefine HAVE_OASYNC 1 #cmakedefine HAVE_OPENSSL 1 #cmakedefine HAVE_O_DIRECT 1 diff --git a/src/libserver/worker_util.c b/src/libserver/worker_util.c index ef2b88578..9733bda3f 100644 --- a/src/libserver/worker_util.c +++ b/src/libserver/worker_util.c @@ -423,16 +423,28 @@ rspamd_worker_set_limits (struct rspamd_main *rspamd_main, } } - if (cf->rlimit_maxcore != 0) { - rlmt.rlim_cur = (rlim_t) cf->rlimit_maxcore; - rlmt.rlim_max = (rlim_t) cf->rlimit_maxcore; + if (rspamd_main->cores_throttling) { + msg_info_main ("disable core files for the new worker, as limits are reached"); + rlmt.rlim_cur = 0; + rlmt.rlim_max = 0; if (setrlimit (RLIMIT_CORE, &rlmt) == -1) { - msg_warn_main ("cannot set max core rlimit: %d, %s", - cf->rlimit_maxcore, + msg_warn_main ("cannot disable core: %s", strerror (errno)); } } + else { + 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 * diff --git a/src/rspamd.c b/src/rspamd.c index 6f2e500f8..004e726b6 100644 --- a/src/rspamd.c +++ b/src/rspamd.c @@ -45,6 +45,10 @@ #include #endif +#ifdef HAVE_NFTW +#include +#endif + #include #ifdef HAVE_SYS_WAIT_H #include @@ -610,6 +614,96 @@ wait_for_workers (gpointer key, gpointer value, gpointer unused) return TRUE; } +struct core_check_cbdata { + struct rspamd_config *cfg; + gsize total_count; + gsize total_size; +}; + +#ifdef HAVE_NFTW + +static struct core_check_cbdata cores_cbdata; + +static gint +rspamd_check_core_cb (const gchar *path, const struct stat *st, + gint flag, struct FTW *ft) +{ + if (S_ISREG (st->st_mode)) { + cores_cbdata.total_count ++; + cores_cbdata.total_size += st->st_size; + } + + return 0; +} + +#endif + +static void +rspamd_check_core_limits (struct rspamd_main *rspamd_main) +{ +#ifdef HAVE_NFTW + struct rspamd_config *cfg = rspamd_main->cfg; + + cores_cbdata.cfg = cfg; + cores_cbdata.total_count = 0; + cores_cbdata.total_size = 0; + + if (cfg->cores_dir && (cfg->max_cores_count || cfg->max_cores_size)) { + if (nftw (cfg->cores_dir, rspamd_check_core_cb, 20, FTW_MOUNT|FTW_PHYS) + == -1) { + msg_err_main ("nftw failed for path %s: %s", cfg->cores_dir, + strerror (errno)); + } + else { + if (!rspamd_main->cores_throttling) { + if (cfg->max_cores_size && + cores_cbdata.total_size > cfg->max_cores_size) { + msg_warn_main ( + "enable cores throttling as size of cores in" + " %s is %Hz, limit is %Hz", + cfg->cores_dir, + cores_cbdata.total_size, + cfg->max_cores_size); + rspamd_main->cores_throttling = TRUE; + } + if (cfg->max_cores_count && + cores_cbdata.total_count > cfg->max_cores_count) { + msg_warn_main ( + "enable cores throttling as count of cores in" + " %s is %z, limit is %z", + cfg->cores_dir, + cores_cbdata.total_count, + cfg->max_cores_count); + rspamd_main->cores_throttling = TRUE; + } + } + else { + if (cfg->max_cores_size && + cores_cbdata.total_size < cfg->max_cores_size) { + msg_info_main ( + "disable cores throttling as size of cores in" + " %s is now %Hz, limit is %Hz", + cfg->cores_dir, + cores_cbdata.total_size, + cfg->max_cores_size); + rspamd_main->cores_throttling = FALSE; + } + if (cfg->max_cores_count && + cores_cbdata.total_count < cfg->max_cores_count) { + msg_info_main ( + "disable cores throttling as count of cores in" + " %s is %z, limit is %z", + cfg->cores_dir, + cores_cbdata.total_count, + cfg->max_cores_count); + rspamd_main->cores_throttling = FALSE; + } + } + } + } +#endif +} + static void reopen_log_handler (gpointer key, gpointer value, gpointer unused) { @@ -721,6 +815,7 @@ rspamd_hup_handler (gint signo, short what, gpointer arg) g_hash_table_foreach (rspamd_main->workers, kill_old_workers, NULL); rspamd_map_remove_all (rspamd_main->cfg); reread_config (rspamd_main); + rspamd_check_core_limits (rspamd_main); spawn_workers (rspamd_main, rspamd_main->ev_base); } @@ -785,6 +880,7 @@ rspamd_cld_handler (gint signo, short what, gpointer arg) WEXITSTATUS (res)); } /* Fork another worker in replace of dead one */ + rspamd_check_core_limits (rspamd_main); rspamd_fork_delayed (cur->cf, cur->index, rspamd_main); } @@ -1116,6 +1212,7 @@ main (gint argc, gchar **argv, gchar **env) event_base_set (ev_base, &usr1_ev); event_add (&usr1_ev, NULL); + rspamd_check_core_limits (rspamd_main); spawn_workers (rspamd_main, ev_base); if (control_fd != -1) { diff --git a/src/rspamd.h b/src/rspamd.h index 61ef25cd4..0095cc093 100644 --- a/src/rspamd.h +++ b/src/rspamd.h @@ -172,6 +172,7 @@ struct rspamd_main { uid_t workers_uid; /**< worker's uid running to */ gid_t workers_gid; /**< worker's gid running to */ gboolean is_privilleged; /**< true if run in privilleged mode */ + gboolean cores_throttling; /**< turn off cores when limits are exceeded */ struct roll_history *history; /**< rolling history */ struct event_base *ev_base; }; -- 2.39.5