Prepare the main cleanup function for the exporting engine (#9099)
Vladimir Kobal committed
May 20, 2020 at 09:30 UTC
98c7260d929a2f6ad2aabb4b27f0d77d49f6cae8
5 files changed
+101
-25
exporting/clean_connectors.c
+19
-18
@@ -3,35 +3,36 @@
3
#include "exporting_engine.h"
4
5
/**
6
- * Clean the instance config.
7
- * @param ptr
6
+ * Clean the instance config
7
+ *
8
+ * @param config an instance config structure.
9
*/
9
-static void clean_instance_config(struct instance_config *ptr)
10
+static void clean_instance_config(struct instance_config *config)
11
{
11
- if (ptr->name)
12
- freez((void *)ptr->name);
12
+ if (config->name)
13
+ freez((void *)config->name);
14
14
- if (ptr->destination)
15
- freez((void *)ptr->destination);
15
+ if (config->destination)
16
+ freez((void *)config->destination);
17
17
- if (ptr->charts_pattern)
18
- simple_pattern_free(ptr->charts_pattern);
18
+ if (config->charts_pattern)
19
+ simple_pattern_free(config->charts_pattern);
20
20
- if (ptr->hosts_pattern)
21
- simple_pattern_free(ptr->hosts_pattern);
21
+ if (config->hosts_pattern)
22
+ simple_pattern_free(config->hosts_pattern);
23
}
24
25
/**
26
* Clean the allocated variables
27
*
27
- * @param ptr a pointer to the structure with variables to clean.
28
+ * @param instance an instance data structure.
29
*/
29
-void clean_instance(struct instance *ptr)
30
+void clean_instance(struct instance *instance)
31
{
31
- clean_instance_config(&ptr->config);
32
- if (ptr->labels)
33
- buffer_free(ptr->labels);
32
+ clean_instance_config(&instance->config);
33
+ if (instance->labels)
34
+ buffer_free(instance->labels);
35
35
- uv_mutex_destroy(&ptr->mutex);
36
- uv_cond_destroy(&ptr->cond_var);
36
+ uv_cond_destroy(&instance->cond_var);
37
+ // uv_mutex_destroy(&instance->mutex);
38
}
exporting/exporting_engine.c
+54
-3
@@ -2,12 +2,63 @@
2
3
#include "exporting_engine.h"
4
5
-static void exporting_main_cleanup(void *ptr) {
5
+static struct engine *engine = NULL;
6
+
7
+/**
8
+ * Clean up the main exporting thread and all connector workers on Netdata exit
9
+ *
10
+ * @param ptr thread data.
11
+ */
12
+static void exporting_main_cleanup(void *ptr)
13
+{
14
struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
15
static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
16
17
info("cleaning up...");
18
19
+ if (!engine) {
20
+ static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
21
+ return;
22
+ }
23
+
24
+ engine->exit = 1;
25
+
26
+ int found = 0;
27
+ usec_t max = 2 * USEC_PER_SEC, step = 50000;
28
+
29
+ for (struct instance *instance = engine->instance_root; instance; instance = instance->next) {
30
+ if (!instance->exited) {
31
+ found++;
32
+ info("stopping worker for instance %s", instance->config.name);
33
+ uv_cond_signal(&instance->cond_var);
34
+ } else
35
+ info("found stopped worker for instance %s", instance->config.name);
36
+ }
37
+
38
+ while (found && max > 0) {
39
+ max -= step;
40
+ info("Waiting %d exporting connectors to finish...", found);
41
+ sleep_usec(step);
42
+ found = 0;
43
+
44
+ for (struct instance *instance = engine->instance_root; instance; instance = instance->next) {
45
+ if (!instance->exited)
46
+ found++;
47
+ }
48
+ }
49
+
50
+ for (struct instance *instance = engine->instance_root; instance;) {
51
+ struct instance *current_instance = instance;
52
+ instance = instance->next;
53
+ clean_instance(current_instance);
54
+ }
55
+
56
+ if (engine->config.prefix)
57
+ freez((void *)engine->config.prefix);
58
+ if (engine->config.hostname)
59
+ freez((void *)engine->config.hostname);
60
+ freez(engine);
61
+
62
static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
63
}
64
@@ -24,7 +75,7 @@ void *exporting_main(void *ptr)
75
{
76
netdata_thread_cleanup_push(exporting_main_cleanup, ptr);
77
27
- struct engine *engine = read_exporting_config();
78
+ engine = read_exporting_config();
79
if (!engine) {
80
info("EXPORTING: no exporting connectors configured");
81
goto cleanup;
@@ -54,7 +105,7 @@ void *exporting_main(void *ptr)
105
send_main_rusage(st_main_rusage, rd_main_user, rd_main_system);
106
107
#ifdef UNIT_TESTING
57
- break;
108
+ return NULL;
109
#endif
110
}
111
exporting/exporting_engine.h
+4
@@ -180,6 +180,8 @@ struct instance {
180
size_t index;
181
struct instance *next;
182
struct engine *engine;
183
+
184
+ volatile sig_atomic_t exited;
185
};
186
187
struct engine {
@@ -192,6 +194,8 @@ struct engine {
194
int mongoc_initialized;
195
196
struct instance *instance_root;
197
+
198
+ volatile sig_atomic_t exit;
199
};
200
201
extern struct instance *prometheus_exporter_instance;
exporting/send_data.c
+21
-2
@@ -140,6 +140,21 @@ void simple_connector_send_buffer(int *sock, int *failures, struct instance *ins
140
}
141
}
142
143
+/**
144
+ * Clean up a simple connector instance on Netdata exit
145
+ *
146
+ * @param instance an instance data structure.
147
+ */
148
+void simple_connector_cleanup(struct instance *instance)
149
+{
150
+ info("EXPORTING: cleaning up instance %s ...", instance->config.name);
151
+
152
+ // TODO free allocated resources
153
+
154
+ info("EXPORTING: instance %s exited", instance->config.name);
155
+ instance->exited = 1;
156
+}
157
+
158
/**
159
* Simple connector worker
160
*
@@ -159,7 +174,7 @@ void simple_connector_worker(void *instance_p)
174
.tv_usec = (instance->config.timeoutms * 1000) % 1000000};
175
int failures = 0;
176
162
- while(!netdata_exit) {
177
+ while(!instance->engine->exit) {
178
179
// reset the monitoring chart counters
180
stats->received_bytes =
@@ -195,7 +210,7 @@ void simple_connector_worker(void *instance_p)
210
stats->reconnects += reconnects;
211
}
212
198
- if(unlikely(netdata_exit)) break;
213
+ if(unlikely(instance->engine->exit)) break;
214
215
// ------------------------------------------------------------------------
216
// if we are connected, send our buffer to the data collecting server
@@ -203,6 +218,8 @@ void simple_connector_worker(void *instance_p)
218
uv_mutex_lock(&instance->mutex);
219
uv_cond_wait(&instance->cond_var, &instance->mutex);
220
221
+ if(unlikely(instance->engine->exit)) break;
222
+
223
if (likely(sock != -1)) {
224
simple_connector_send_buffer(&sock, &failures, instance);
225
} else {
@@ -238,4 +255,6 @@ void simple_connector_worker(void *instance_p)
255
break;
256
#endif
257
}
258
+
259
+ simple_connector_cleanup(instance);
260
}
exporting/tests/test_exporting_engine.c
+3
-2
@@ -65,8 +65,6 @@ static void test_exporting_engine(void **state)
65
expect_value(__wrap_send_main_rusage, rd_user, NULL);
66
expect_value(__wrap_send_main_rusage, rd_system, NULL);
67
68
- expect_function_call(__wrap_info_int);
69
-
68
void *ptr = malloc(sizeof(struct netdata_static_thread));
69
assert_ptr_equal(exporting_main(ptr), NULL);
70
assert_int_equal(engine->now, 2);
@@ -668,6 +666,9 @@ static void test_simple_connector_worker(void **state)
666
expect_value(__wrap_send_internal_metrics, instance, instance);
667
will_return(__wrap_send_internal_metrics, 0);
668
669
+ expect_function_call(__wrap_info_int);
670
+ expect_function_call(__wrap_info_int);
671
+
672
simple_connector_worker(instance);
673
674
assert_int_equal(stats->buffered_metrics, 0);