@cryptotaxi247 / netdata-1 / commits / f5a85f774

Added code to release memory used by the global GUID map (#9729)

Fixed memory leak issues associated with the global GUID map during agent shutdown

Stelios Fragkakis committed Aug 20, 2020 at 18:50 UTC f5a85f7747f04ae3146f0a2cdf948531fed0d47c
6 files changed +74 -41
daemon/main.c
+3 -1
@@ -60,7 +60,9 @@ void netdata_cleanup_and_exit(int ret) {
60 #ifdef ENABLE_HTTPS
61 security_clean_openssl();
62 #endif
63 -
63 +#ifdef ENABLE_DBENGINE
64 + free_global_guid_map();
65 +#endif
66 info("EXIT: all done - netdata is now exiting - bye bye...");
67 exit(ret);
68 }
database/engine/global_uuid_map/global_uuid_map.c
+51 -36
@@ -9,6 +9,51 @@ static uv_rwlock_t object_lock;
9 static uv_rwlock_t global_lock;
10
11
12 +void free_global_guid_map()
13 +{
14 + JudyHSFreeArray(&JGUID_map, PJE0);
15 + JudyHSFreeArray(&JGUID_object_map, PJE0);
16 +}
17 +
18 +static void free_single_uuid(uuid_t *uuid)
19 +{
20 + Pvoid_t *PValue, *PValue1;
21 + char *existing_object;
22 + Word_t size;
23 +
24 + PValue = JudyHSGet(JGUID_map, (void *) uuid, (Word_t) sizeof(uuid_t));
25 + if (likely(PValue)) {
26 + existing_object = *PValue;
27 + GUID_TYPE object_type = existing_object[0];
28 + size = (Word_t)object_type ? (object_type * 16) + 1 : strlen((char *)existing_object + 1) + 2;
29 + PValue1 = JudyHSGet(JGUID_object_map, (void *)existing_object, (Word_t)size);
30 + if (PValue1 && *PValue1) {
31 + freez(*PValue1);
32 + }
33 + JudyHSDel(&JGUID_object_map, (void *)existing_object,
34 + (Word_t)object_type ? (object_type * 16) + 1 : strlen((char *)existing_object + 1) + 2, PJE0);
35 + JudyHSDel(&JGUID_map, (void *)uuid, (Word_t)sizeof(uuid_t), PJE0);
36 + freez(existing_object);
37 + }
38 +}
39 +
40 +void free_uuid(uuid_t *uuid)
41 +{
42 + GUID_TYPE ret;
43 + char object[49];
44 +
45 + ret = find_object_by_guid(uuid, object, sizeof(object));
46 + if (GUID_TYPE_DIMENSION == ret)
47 + free_single_uuid((uuid_t *)(object + 16 + 16));
48 +
49 + if (GUID_TYPE_CHART == ret)
50 + free_single_uuid((uuid_t *)(object + 16));
51 +
52 + free_single_uuid(uuid);
53 + return;
54 +}
55 +
56 +
57 void dump_object(uuid_t *index, void *object)
58 {
59 char uuid_s[36 + 1];
@@ -101,34 +146,6 @@ static inline int guid_store_nolock(uuid_t *uuid, void *object, GUID_TYPE object
146 }
147
148
104 -inline int guid_store(uuid_t *uuid, char *object, GUID_TYPE object_type)
105 -{
106 - uv_rwlock_wrlock(&global_lock);
107 - int rc = guid_store_nolock(uuid, object, object_type);
108 - uv_rwlock_wrunlock(&global_lock);
109 - return rc;
110 -}
111 -
112 -/*
113 - * This can be used to bulk load entries into the global map
114 - *
115 - * A lock must be aquired since it will call guid_store_nolock
116 - * with a "no lock" parameter.
117 - *
118 - * Note: object memory must be allocated by caller and not released
119 - */
120 -int guid_bulk_load(char *uuid, char *object)
121 -{
122 - uuid_t target_uuid;
123 - if (likely(!uuid_parse(uuid, target_uuid))) {
124 -#ifdef NETDATA_INTERNAL_CHECKS
125 - debug(D_GUIDLOG,"Mapping GUID [%s] on [%s]", uuid, object);
126 -#endif
127 - return guid_store_nolock(&target_uuid, object, GUID_TYPE_CHAR);
128 - }
129 - return 1;
130 -}
131 -
149 /*
150 * Given a GUID, find if an object is stored
151 * - Optionally return the object
@@ -151,15 +168,19 @@ GUID_TYPE find_object_by_guid(uuid_t *uuid, char *object, size_t max_bytes)
168 if (likely(object && max_bytes)) {
169 switch (value_type) {
170 case GUID_TYPE_CHAR:
154 - if (unlikely(max_bytes - 1 < strlen((char *) *PValue+1)))
171 + if (unlikely(max_bytes - 1 < strlen((char *) *PValue+1))) {
172 + uv_rwlock_rdunlock(&global_lock);
173 return GUID_TYPE_NOSPACE;
174 + }
175 strncpyz(object, (char *) *PValue+1, max_bytes - 1);
176 break;
177 case GUID_TYPE_HOST:
178 case GUID_TYPE_CHART:
179 case GUID_TYPE_DIMENSION:
161 - if (unlikely(max_bytes < (size_t) value_type * 16))
180 + if (unlikely(max_bytes < (size_t) value_type * 16)) {
181 + uv_rwlock_rdunlock(&global_lock);
182 return GUID_TYPE_NOSPACE;
183 + }
184 memcpy(object, *PValue+1, value_type * 16);
185 break;
186 default:
@@ -265,12 +286,6 @@ void init_global_guid_map()
286 fatal_assert(0 == uv_rwlock_init(&guid_lock));
287 fatal_assert(0 == uv_rwlock_init(&object_lock));
288 fatal_assert(0 == uv_rwlock_init(&global_lock));
268 -
269 -// int rc = guid_bulk_load("6fc56a64-05d7-47a7-bc82-7f3235d8cbda","d6b37186-74db-11ea-88b2-0bf5095b1f9e/cgroup_qemu_ubuntu18.04.cpu_per_core/cpu3");
270 -// rc = guid_bulk_load("75c6fa02-97cc-40c1-aacd-a0132190472e","d6b37186-74db-11ea-88b2-0bf5095b1f9e/services.throttle_io_ops_write/system.slice_setvtrgb.service");
271 -// if (rc == 0)
272 -// info("BULK GUID load successful");
273 -
289 return;
290 }
291
database/engine/global_uuid_map/global_uuid_map.h
+2 -3
@@ -16,11 +16,10 @@ typedef enum guid_type {
16 GUID_TYPE_NOSPACE
17 } GUID_TYPE;
18
19 -extern int guid_store(uuid_t *uuid, char *object, GUID_TYPE);
19 extern GUID_TYPE find_object_by_guid(uuid_t *uuid, char *object, size_t max_bytes);
20 extern int find_guid_by_object(char *object, uuid_t *uuid, GUID_TYPE);
21 extern void init_global_guid_map();
22 extern int find_or_generate_guid(void *object, uuid_t *uuid, GUID_TYPE object_type, int replace_instead_of_generate);
24 -
25 -
23 +extern void free_uuid(uuid_t *uuid);
24 +extern void free_global_guid_map();
25 #endif //NETDATA_GLOBAL_UUID_MAP_H
database/rrddim.c
+8 -1
@@ -487,7 +487,6 @@ void rrddim_free_custom(RRDSET *st, RRDDIM *rd, int db_rotated)
487 #endif
488 }
489 }
490 - freez(rd->state);
490
491 if(rd == st->dimensions)
492 st->dimensions = rd->next;
@@ -518,6 +517,7 @@ void rrddim_free_custom(RRDSET *st, RRDDIM *rd, int db_rotated)
517 debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name);
518 freez((void *)rd->id);
519 freez(rd->cache_filename);
520 + freez(rd->state);
521 munmap(rd, rd->memsize);
522 break;
523
@@ -527,6 +527,13 @@ void rrddim_free_custom(RRDSET *st, RRDDIM *rd, int db_rotated)
527 debug(D_RRD_CALLS, "Removing dimension '%s'.", rd->name);
528 freez((void *)rd->id);
529 freez(rd->cache_filename);
530 +#ifdef ENABLE_DBENGINE
531 + if (rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
532 + free_uuid(rd->state->metric_uuid);
533 + freez(rd->state->metric_uuid);
534 + }
535 +#endif
536 + freez(rd->state);
537 freez(rd);
538 break;
539 }
database/rrdhost.c
+4
@@ -879,6 +879,10 @@ void rrdhost_free(RRDHOST *host) {
879 netdata_rwlock_destroy(&host->labels_rwlock);
880 netdata_rwlock_destroy(&host->health_log.alarm_log_rwlock);
881 netdata_rwlock_destroy(&host->rrdhost_rwlock);
882 +
883 +#ifdef ENABLE_DBENGINE
884 + free_uuid(&host->host_uuid);
885 +#endif
886 freez(host);
887
888 rrd_hosts_available--;
database/rrdset.c
+6
@@ -388,6 +388,12 @@ void rrdset_free(RRDSET *st) {
388 case RRD_MEMORY_MODE_ALLOC:
389 case RRD_MEMORY_MODE_NONE:
390 case RRD_MEMORY_MODE_DBENGINE:
391 +#ifdef ENABLE_DBENGINE
392 + if (st->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
393 + free_uuid(st->chart_uuid);
394 + freez(st->chart_uuid);
395 + }
396 +#endif
397 freez(st);
398 break;
399 }