Browse Source

fix memory leaks and mismatches of the use of the z functions for allocations (#12841)

* fix mismatches of the use of the z functions for allocations

* when there was no memory; the original name of the dimensions was freed, and with mismatching deallocator..

* fixed memory leak at rrdeng_load_metric_*() functions

* fixed memory leak on exit of plugins.d parser

* fixed memory leak on plugins and streaming receiver threads exit

* fixed compiler warnings
Costa Tsaousis 2 years ago
parent
commit
79444d3645

+ 22 - 19
collectors/plugins.d/pluginsd_parser.c

@@ -725,6 +725,11 @@ PARSER_RC metalog_pluginsd_host(char **words, void *user, PLUGINSD_ACTION  *plug
     return PARSER_RC_OK;
 }
 
+static void pluginsd_process_thread_cleanup(void *ptr) {
+    PARSER *parser = (PARSER *)ptr;
+    parser_destroy(parser);
+}
+
 // New plugins.d parser
 
 inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations)
@@ -743,19 +748,18 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int
     }
     clearerr(fp);
 
-    PARSER_USER_OBJECT *user = callocz(1, sizeof(*user));
-    ((PARSER_USER_OBJECT *) user)->enabled = cd->enabled;
-    ((PARSER_USER_OBJECT *) user)->host = host;
-    ((PARSER_USER_OBJECT *) user)->cd = cd;
-    ((PARSER_USER_OBJECT *) user)->trust_durations = trust_durations;
+    PARSER_USER_OBJECT user = {
+        .enabled = cd->enabled,
+        .host = host,
+        .cd = cd,
+        .trust_durations = trust_durations
+    };
 
-    PARSER *parser = parser_init(host, user, fp, PARSER_INPUT_SPLIT);
+    PARSER *parser = parser_init(host, &user, fp, PARSER_INPUT_SPLIT);
 
-    if (unlikely(!parser)) {
-        error("Failed to initialize parser");
-        cd->serial_failures++;
-        return 0;
-    }
+    // this keeps the parser with its current value
+    // so, parser needs to be allocated before pushing it
+    netdata_thread_cleanup_push(pluginsd_process_thread_cleanup, parser);
 
     parser->plugins_action->begin_action          = &pluginsd_begin_action;
     parser->plugins_action->flush_action          = &pluginsd_flush_action;
@@ -770,25 +774,24 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int
     parser->plugins_action->clabel_commit_action  = &pluginsd_clabel_commit_action;
     parser->plugins_action->clabel_action         = &pluginsd_clabel_action;
 
-    user->parser = parser;
+    user.parser = parser;
 
     while (likely(!parser_next(parser))) {
         if (unlikely(netdata_exit || parser_action(parser,  NULL)))
             break;
     }
-    info("PARSER ended");
-
-    parser_destroy(parser);
 
-    cd->enabled = ((PARSER_USER_OBJECT *) user)->enabled;
-    size_t count = ((PARSER_USER_OBJECT *) user)->count;
+    // free parser with the pop function
+    netdata_thread_cleanup_pop(1);
 
-    freez(user);
+    cd->enabled = user.enabled;
+    size_t count = user.count;
 
     if (likely(count)) {
         cd->successful_collections += count;
         cd->serial_failures = 0;
-    } else
+    }
+    else
         cd->serial_failures++;
 
     return count;

+ 1 - 1
collectors/proc.plugin/proc_spl_kstat_zfs.c

@@ -290,7 +290,7 @@ int update_zfs_pool_state_chart(char *name, void *pool_p, void *update_every_p)
         }
     } else {
         disable_zfs_pool_state(pool);
-        struct deleted_zfs_pool *new = calloc(1, sizeof(struct deleted_zfs_pool));
+        struct deleted_zfs_pool *new = callocz(1, sizeof(struct deleted_zfs_pool));
         new->name = strdupz(name);
         new->next = deleted_zfs_pools;
         deleted_zfs_pools = new;

+ 1 - 1
daemon/main.c

@@ -1235,7 +1235,7 @@ int main(int argc, char **argv) {
     // initialize rrd, registry, health, rrdpush, etc.
 
     netdata_anonymous_statistics_enabled=-1;
-    struct rrdhost_system_info *system_info = calloc(1, sizeof(struct rrdhost_system_info));
+    struct rrdhost_system_info *system_info = callocz(1, sizeof(struct rrdhost_system_info));
     get_system_info(system_info);
     system_info->hops = 0;
     get_install_type(&system_info->install_type, &system_info->prebuilt_arch, &system_info->prebuilt_dist);

+ 7 - 13
database/engine/metadata_log/logfile.c

@@ -375,19 +375,15 @@ static int scan_metalog_files(struct metalog_instance *ctx)
     struct metalog_pluginsd_state metalog_parser_state;
     metalog_pluginsd_state_init(&metalog_parser_state, ctx);
 
-    PARSER_USER_OBJECT metalog_parser_object;
-    metalog_parser_object.enabled = cd.enabled;
-    metalog_parser_object.host = ctx->rrdeng_ctx->host;
-    metalog_parser_object.cd = &cd;
-    metalog_parser_object.trust_durations = 0;
-    metalog_parser_object.private = &metalog_parser_state;
+    PARSER_USER_OBJECT metalog_parser_object = {
+        .enabled = cd.enabled,
+        .host = ctx->rrdeng_ctx->host,
+        .cd = &cd,
+        .trust_durations = 0,
+        .private = &metalog_parser_state
+    };
 
     PARSER *parser = parser_init(metalog_parser_object.host, &metalog_parser_object, NULL, PARSER_INPUT_SPLIT);
-    if (unlikely(!parser)) {
-        error("Failed to initialize metadata log parser.");
-        failed_to_load = matched_files;
-        goto after_failed_to_parse;
-    }
     parser_add_keyword(parser, PLUGINSD_KEYWORD_HOST, metalog_pluginsd_host);
     parser_add_keyword(parser, PLUGINSD_KEYWORD_GUID, pluginsd_guid);
     parser_add_keyword(parser, PLUGINSD_KEYWORD_CONTEXT, pluginsd_context);
@@ -428,10 +424,8 @@ static int scan_metalog_files(struct metalog_instance *ctx)
     size_t count __maybe_unused = metalog_parser_object.count;
 
     debug(D_METADATALOG, "Parsing count=%u", (unsigned)count);
-after_failed_to_parse:
 
     freez(metalogfiles);
-
     return matched_files;
 }
 

+ 5 - 1
database/engine/rrdengineapi.c

@@ -540,7 +540,7 @@ void rrdeng_load_metric_init(RRDDIM *rd, struct rrddim_query_handle *rrdimm_hand
     rrdimm_handle->start_time = start_time;
     rrdimm_handle->end_time = end_time;
 
-    handle = calloc(1, sizeof(struct rrdeng_query_handle));
+    handle = callocz(1, sizeof(struct rrdeng_query_handle));
     handle->next_page_time = start_time;
     handle->now = start_time;
     handle->position = 0;
@@ -674,6 +674,10 @@ void rrdeng_load_metric_finalize(struct rrddim_query_handle *rrdimm_handle)
 #endif
         pg_cache_put(ctx, descr);
     }
+
+    // whatever is allocated at rrdeng_load_metric_init() should be freed here
+    freez(handle);
+    rrdimm_handle->handle = NULL;
 }
 
 time_t rrdeng_metric_latest_time(RRDDIM *rd)

+ 9 - 13
database/rrdcalc.c

@@ -287,19 +287,15 @@ inline uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const ch
 char *alarm_name_with_dim(char *name, size_t namelen, const char *dim, size_t dimlen) {
     char *newname,*move;
 
-    newname = malloc(namelen + dimlen + 2);
-    if(newname) {
-        move = newname;
-        memcpy(move, name, namelen);
-        move += namelen;
-
-        *move++ = '_';
-        memcpy(move, dim, dimlen);
-        move += dimlen;
-        *move = '\0';
-    } else {
-        newname = name;
-    }
+    newname = mallocz(namelen + dimlen + 2);
+    move = newname;
+    memcpy(move, name, namelen);
+    move += namelen;
+
+    *move++ = '_';
+    memcpy(move, dim, dimlen);
+    move += dimlen;
+    *move = '\0';
 
     return newname;
 }

+ 18 - 18
database/rrddim.c

@@ -169,31 +169,31 @@ static time_t rrddim_query_oldest_time(RRDDIM *rd) {
 
 void rrdcalc_link_to_rrddim(RRDDIM *rd, RRDSET *st, RRDHOST *host) {
     RRDCALC *rrdc;
+    
     for (rrdc = host->alarms_with_foreach; rrdc ; rrdc = rrdc->next) {
         if (simple_pattern_matches(rrdc->spdim, rd->id) || simple_pattern_matches(rrdc->spdim, rd->name)) {
             if (rrdc->hash_chart == st->hash_name || !strcmp(rrdc->chart, st->name) || !strcmp(rrdc->chart, st->id)) {
                 char *name = alarm_name_with_dim(rrdc->name, strlen(rrdc->name), rd->name, strlen(rd->name));
-                if (name) {
-                    if(rrdcalc_exists(host, st->name, name, 0, 0)){
-                        freez(name);
-                        continue;
-                    }
+                if(rrdcalc_exists(host, st->name, name, 0, 0)) {
+                    freez(name);
+                    continue;
+                }
 
-                    netdata_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
-                    RRDCALC *child = rrdcalc_create_from_rrdcalc(rrdc, host, name, rd->name);
-                    netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
-
-                    if (child) {
-                        rrdcalc_add_to_host(host, child);
-                        RRDCALC *rdcmp  = (RRDCALC *) avl_insert_lock(&(host)->alarms_idx_health_log,(avl_t *)child);
-                        if (rdcmp != child) {
-                            error("Cannot insert the alarm index ID %s",child->name);
-                        }
-                    } else {
-                        error("Cannot allocate a new alarm.");
-                        rrdc->foreachcounter--;
+                netdata_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
+                RRDCALC *child = rrdcalc_create_from_rrdcalc(rrdc, host, name, rd->name);
+                netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+
+                if (child) {
+                    rrdcalc_add_to_host(host, child);
+                    RRDCALC *rdcmp  = (RRDCALC *) avl_insert_lock(&(host)->alarms_idx_health_log,(avl_t *)child);
+                    if (rdcmp != child) {
+                        error("Cannot insert the alarm index ID %s",child->name);
                     }
                 }
+                else {
+                    error("Cannot allocate a new alarm.");
+                    rrdc->foreachcounter--;
+                }
             }
         }
     }

+ 1 - 11
parser/parser.c

@@ -33,20 +33,12 @@ PARSER *parser_init(RRDHOST *host, void *user, void *input, PARSER_INPUT_TYPE fl
     PARSER *parser;
 
     parser = callocz(1, sizeof(*parser));
-
-    if (unlikely(!parser))
-        return NULL;
-
     parser->plugins_action = callocz(1, sizeof(PLUGINSD_ACTION));
-    if (unlikely(!parser->plugins_action)) {
-        freez(parser);
-        return NULL;
-    }
-
     parser->user = user;
     parser->input = input;
     parser->flags = flags;
     parser->host = host;
+
 #ifdef ENABLE_HTTPS
     parser->bytesleft = 0;
     parser->readfrom = NULL;
@@ -181,9 +173,7 @@ void parser_destroy(PARSER *parser)
     }
 
     freez(parser->plugins_action);
-
     freez(parser);
-    return;
 }
 
 

+ 28 - 19
streaming/receiver.c

@@ -338,26 +338,31 @@ static char *receiver_next_line(struct receiver_state *r, int *pos) {
     return NULL;
 }
 
+static void streaming_parser_thread_cleanup(void *ptr) {
+    PARSER *parser = (PARSER *)ptr;
+    parser_destroy(parser);
+}
+
 size_t streaming_parser(struct receiver_state *rpt, struct plugind *cd, FILE *fp) {
     size_t result;
-    PARSER_USER_OBJECT *user = callocz(1, sizeof(*user));
-    user->enabled = cd->enabled;
-    user->host = rpt->host;
-    user->opaque = rpt;
-    user->cd = cd;
-    user->trust_durations = 0;
-
-    PARSER *parser = parser_init(rpt->host, user, fp, PARSER_INPUT_SPLIT);
+
+    PARSER_USER_OBJECT user = {
+        .enabled = cd->enabled,
+        .host = rpt->host,
+        .opaque = rpt,
+        .cd = cd,
+        .trust_durations = 0
+    };
+
+    PARSER *parser = parser_init(rpt->host, &user, fp, PARSER_INPUT_SPLIT);
+
+    // this keeps the parser with its current value
+    // so, parser needs to be allocated before pushing it
+    netdata_thread_cleanup_push(streaming_parser_thread_cleanup, parser);
+
     parser_add_keyword(parser, "TIMESTAMP", streaming_timestamp);
     parser_add_keyword(parser, "CLAIMED_ID", streaming_claimed_id);
 
-    if (unlikely(!parser)) {
-        error("Failed to initialize parser");
-        cd->serial_failures++;
-        freez(user);
-        return 0;
-    }
-
     parser->plugins_action->begin_action     = &pluginsd_begin_action;
     parser->plugins_action->flush_action     = &pluginsd_flush_action;
     parser->plugins_action->end_action       = &pluginsd_end_action;
@@ -371,12 +376,13 @@ size_t streaming_parser(struct receiver_state *rpt, struct plugind *cd, FILE *fp
     parser->plugins_action->clabel_commit_action  = &pluginsd_clabel_commit_action;
     parser->plugins_action->clabel_action    = &pluginsd_clabel_action;
 
-    user->parser = parser;
+    user.parser = parser;
 
 #ifdef ENABLE_COMPRESSION
     if (rpt->decompressor)
         rpt->decompressor->reset(rpt->decompressor);
 #endif
+
     do{
         if (receiver_read(rpt, fp))
             break;
@@ -389,10 +395,13 @@ size_t streaming_parser(struct receiver_state *rpt, struct plugind *cd, FILE *fp
         rpt->last_msg_t = now_realtime_sec();
     }
     while(!netdata_exit);
+
 done:
-    result= user->count;
-    freez(user);
-    parser_destroy(parser);
+    result = user.count;
+
+    // free parser with the pop function
+    netdata_thread_cleanup_pop(1);
+
     return result;
 }
 

+ 1 - 1
web/api/queries/des/des.c

@@ -70,7 +70,7 @@ static inline void set_beta(RRDR *r, struct grouping_des *g) {
 }
 
 void *grouping_create_des(RRDR *r) {
-    struct grouping_des *g = (struct grouping_des *)malloc(sizeof(struct grouping_des));
+    struct grouping_des *g = (struct grouping_des *)mallocz(sizeof(struct grouping_des));
     set_alpha(r, g);
     set_beta(r, g);
     g->level = 0.0;