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
}