mirror of
https://github.com/netdata/netdata.git
synced 2025-04-23 13:00:23 +00:00
Fix LSAN and memory leaks (#19819)
* add SIGUSR1 for exiting immediately, so that LSAN can check for leaks * fix system info leak * adapt to changed semantics of rrdhost system_info * fix memory leak in rrdcontexts when matching alerts * do not system info after it was freed * allow sentry to send its reports
This commit is contained in:
parent
e3484260d3
commit
ec48ad55ef
11 changed files with 46 additions and 27 deletions
src
daemon
database
plugins.d
streaming
|
@ -318,12 +318,12 @@ void netdata_cleanup_and_exit(EXIT_REASON reason, const char *action, const char
|
|||
|
||||
watcher_shutdown_end();
|
||||
watcher_thread_stop();
|
||||
curl_global_cleanup();
|
||||
|
||||
daemon_status_file_shutdown_step(NULL);
|
||||
daemon_status_file_update_status(DAEMON_STATUS_EXITED);
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
curl_global_cleanup();
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
@ -335,12 +335,15 @@ void netdata_cleanup_and_exit(EXIT_REASON reason, const char *action, const char
|
|||
abort();
|
||||
} else {
|
||||
nd_sentry_fini();
|
||||
curl_global_cleanup();
|
||||
exit(ret);
|
||||
}
|
||||
#else
|
||||
if(ret)
|
||||
_exit(ret);
|
||||
else
|
||||
else {
|
||||
curl_global_cleanup();
|
||||
exit(ret);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1026,20 +1026,19 @@ int netdata_main(int argc, char **argv) {
|
|||
struct rrdhost_system_info *system_info = rrdhost_system_info_create();
|
||||
rrdhost_system_info_detect(system_info);
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
delta_startup_time("install type");
|
||||
|
||||
get_install_type(system_info);
|
||||
|
||||
set_late_analytics_variables(system_info);
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
delta_startup_time("RRD structures");
|
||||
|
||||
abort_on_fatal_disable();
|
||||
if(rrd_init(netdata_configured_hostname, system_info, false)) {
|
||||
set_late_analytics_variables(system_info);
|
||||
if (rrd_init(netdata_configured_hostname, system_info, false))
|
||||
fatal("Cannot initialize localhost instance with name '%s'.", netdata_configured_hostname);
|
||||
}
|
||||
|
||||
abort_on_fatal_enable();
|
||||
system_info = NULL; // system_info is now freed by rrd_init
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
delta_startup_time("localhost labels");
|
||||
|
@ -1064,7 +1063,6 @@ int netdata_main(int argc, char **argv) {
|
|||
|
||||
netdata_conf_section_web();
|
||||
|
||||
set_late_analytics_variables(system_info);
|
||||
for (i = 0; static_threads[i].name != NULL ; i++) {
|
||||
struct netdata_static_thread *st = &static_threads[i];
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
typedef enum signal_action {
|
||||
NETDATA_SIGNAL_IGNORE,
|
||||
NETDATA_SIGNAL_EXIT_CLEANLY,
|
||||
#if defined(FSANITIZE_ADDRESS)
|
||||
NETDATA_SIGNAL_EXIT_NOW,
|
||||
#endif
|
||||
NETDATA_SIGNAL_REOPEN_LOGS,
|
||||
NETDATA_SIGNAL_RELOAD_HEALTH,
|
||||
NETDATA_SIGNAL_DEADLY,
|
||||
|
@ -23,6 +26,9 @@ static struct {
|
|||
{ SIGQUIT, "SIGQUIT", 0, NETDATA_SIGNAL_EXIT_CLEANLY, EXIT_REASON_SIGQUIT },
|
||||
{ SIGTERM, "SIGTERM", 0, NETDATA_SIGNAL_EXIT_CLEANLY, EXIT_REASON_SIGTERM },
|
||||
{ SIGHUP, "SIGHUP", 0, NETDATA_SIGNAL_REOPEN_LOGS, EXIT_REASON_NONE },
|
||||
#if defined(FSANITIZE_ADDRESS)
|
||||
{ SIGUSR1, "SIGUSR1", 0, NETDATA_SIGNAL_EXIT_NOW, EXIT_REASON_NONE },
|
||||
#endif
|
||||
{ SIGUSR2, "SIGUSR2", 0, NETDATA_SIGNAL_RELOAD_HEALTH, EXIT_REASON_NONE },
|
||||
{ SIGBUS, "SIGBUS", 0, NETDATA_SIGNAL_DEADLY, EXIT_REASON_SIGBUS },
|
||||
{ SIGSEGV, "SIGSEGV", 0, NETDATA_SIGNAL_DEADLY, EXIT_REASON_SIGSEGV },
|
||||
|
@ -38,6 +44,11 @@ static void signal_handler(int signo) {
|
|||
|
||||
signals_waiting[i].count++;
|
||||
|
||||
#if defined(FSANITIZE_ADDRESS)
|
||||
if(signals_waiting[i].action == NETDATA_SIGNAL_EXIT_NOW)
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
if(signals_waiting[i].action == NETDATA_SIGNAL_DEADLY) {
|
||||
// Update the status file
|
||||
daemon_status_file_deadly_signal_received(signals_waiting[i].reason);
|
||||
|
|
|
@ -123,9 +123,10 @@ bool rrdcontext_matches_alert(struct rrdcontext_to_json_v2_data *ctl, RRDCONTEXT
|
|||
sizeof(struct alert_by_x_entry),
|
||||
rcl);
|
||||
|
||||
char *module = NULL;
|
||||
rrdlabels_get_value_strdup_or_null(st->rrdlabels, &module, "_collect_module");
|
||||
if(!module || !*module) module = "[unset]";
|
||||
char module[128];
|
||||
rrdlabels_get_value_strcpyz(st->rrdlabels, module, sizeof(module), "_collect_module");
|
||||
if(!*module)
|
||||
strncpyz(module, "[unset]", sizeof(module) - 1);
|
||||
|
||||
dictionary_set_advanced(ctl->alerts.by_module,
|
||||
module,
|
||||
|
|
|
@ -142,6 +142,7 @@ int rrd_init(const char *hostname, struct rrdhost_system_info *system_info, bool
|
|||
, 1
|
||||
, 0
|
||||
);
|
||||
rrdhost_system_info_free(system_info);
|
||||
|
||||
if (unlikely(!localhost))
|
||||
return 1;
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
// coverity[ +tainted_string_sanitize_content : arg-0 ]
|
||||
static inline void coverity_remove_taint(char *s __maybe_unused) { }
|
||||
|
||||
void rrdhost_system_info_swap(struct rrdhost_system_info *a, struct rrdhost_system_info *b) {
|
||||
if(a && b)
|
||||
SWAP(*a, *b);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// RRDHOST - set system info from environment variables
|
||||
// system_info fields must be heap allocated or NULL
|
||||
|
|
|
@ -100,5 +100,6 @@ void rrdhost_system_info_to_node_info(struct rrdhost_system_info *system_info, s
|
|||
void rrdhost_system_info_to_streaming_function_array(BUFFER *wb, struct rrdhost_system_info *system_info);
|
||||
|
||||
void get_daemon_status_fields_from_system_info(DAEMON_STATUS_FILE *ds);
|
||||
void rrdhost_system_info_swap(struct rrdhost_system_info *a, struct rrdhost_system_info *b);
|
||||
|
||||
#endif //NETDATA_RRDHOST_SYSTEM_INFO_H
|
||||
|
|
|
@ -368,7 +368,8 @@ RRDHOST *rrdhost_create(
|
|||
|
||||
rrdhost_set_replication_parameters(host, memory_mode, replication_period, replication_step);
|
||||
|
||||
host->system_info = system_info;
|
||||
host->system_info = rrdhost_system_info_create();
|
||||
rrdhost_system_info_swap(host->system_info, system_info);
|
||||
|
||||
rrdset_index_init(host);
|
||||
|
||||
|
@ -543,12 +544,8 @@ static void rrdhost_update(RRDHOST *host
|
|||
|
||||
host->health.enabled = (mode == RRD_DB_MODE_NONE) ? 0 : health;
|
||||
|
||||
{
|
||||
struct rrdhost_system_info *old = host->system_info;
|
||||
host->system_info = system_info;
|
||||
rrdhost_flag_set(host, RRDHOST_FLAG_METADATA_INFO | RRDHOST_FLAG_METADATA_CLAIMID | RRDHOST_FLAG_METADATA_UPDATE);
|
||||
rrdhost_system_info_free(old);
|
||||
}
|
||||
rrdhost_system_info_swap(host->system_info, system_info);
|
||||
rrdhost_flag_set(host, RRDHOST_FLAG_METADATA_INFO | RRDHOST_FLAG_METADATA_CLAIMID | RRDHOST_FLAG_METADATA_UPDATE);
|
||||
|
||||
rrdhost_init_os(host, os);
|
||||
rrdhost_init_timezone(host, timezone, abbrev_timezone, utc_offset);
|
||||
|
@ -676,10 +673,8 @@ RRDHOST *rrdhost_find_or_create(
|
|||
RRDHOST *host = rrdhost_find_by_guid(guid);
|
||||
if (unlikely(host && host->rrd_memory_mode != mode && rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED))) {
|
||||
|
||||
if (likely(!archived && rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD))) {
|
||||
rrdhost_system_info_free(system_info);
|
||||
if (likely(!archived && rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD)))
|
||||
return host;
|
||||
}
|
||||
|
||||
/* If a legacy memory mode instantiates all dbengine state must be discarded to avoid inconsistencies */
|
||||
nd_log(NDLS_DAEMON, NDLP_INFO,
|
||||
|
@ -748,9 +743,6 @@ RRDHOST *rrdhost_find_or_create(
|
|||
, system_info);
|
||||
}
|
||||
|
||||
if(!host)
|
||||
rrdhost_system_info_free(system_info);
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,8 @@ static int create_host_callback(void *data, int argc, char **argv, char **column
|
|||
system_info,
|
||||
1);
|
||||
|
||||
rrdhost_system_info_free(system_info);
|
||||
|
||||
if (likely(host)) {
|
||||
if (is_ephemeral)
|
||||
rrdhost_option_set(host, RRDHOST_OPTION_EPHEMERAL_HOST);
|
||||
|
|
|
@ -194,6 +194,8 @@ static inline PARSER_RC pluginsd_host_define_end(char **words __maybe_unused, si
|
|||
if(!parser->user.host_define.parsing_host)
|
||||
return PLUGINSD_DISABLE_PLUGIN(parser, PLUGINSD_KEYWORD_HOST_DEFINE_END, "missing initialization, send " PLUGINSD_KEYWORD_HOST_DEFINE " before this");
|
||||
|
||||
struct rrdhost_system_info *system_info = rrdhost_system_info_from_host_labels(parser->user.host_define.rrdlabels);
|
||||
|
||||
RRDHOST *host = rrdhost_find_or_create(
|
||||
string2str(parser->user.host_define.hostname),
|
||||
string2str(parser->user.host_define.hostname),
|
||||
|
@ -215,9 +217,11 @@ static inline PARSER_RC pluginsd_host_define_end(char **words __maybe_unused, si
|
|||
stream_receive.replication.enabled,
|
||||
stream_receive.replication.period,
|
||||
stream_receive.replication.step,
|
||||
rrdhost_system_info_from_host_labels(parser->user.host_define.rrdlabels),
|
||||
system_info,
|
||||
false);
|
||||
|
||||
rrdhost_system_info_free(system_info);
|
||||
|
||||
rrdhost_option_set(host, RRDHOST_OPTION_VIRTUAL_HOST);
|
||||
rrdhost_flag_set(host, RRDHOST_FLAG_COLLECTOR_ONLINE);
|
||||
object_state_activate_if_not_activated(&host->state_id);
|
||||
|
|
|
@ -173,7 +173,8 @@ static bool stream_receiver_send_first_response(struct receiver_state *rpt) {
|
|||
rpt->config.replication.step,
|
||||
rpt->system_info,
|
||||
0);
|
||||
// IMPORTANT: system_info is now consumed!
|
||||
|
||||
rrdhost_system_info_free(rpt->system_info);
|
||||
rpt->system_info = NULL;
|
||||
|
||||
if(!host) {
|
||||
|
|
Loading…
Add table
Reference in a new issue