Improve dyncfg exit (#15824)
Timotej S committed
Aug 17, 2023 at 10:21 UTC
cec38dd7de6a068b2bfc06712e766e111982d604
3 files changed
+85
-45
daemon/static_threads.h
-33
@@ -5,39 +5,6 @@
5
6
#include "common.h"
7
8
-struct netdata_static_thread {
9
- // the name of the thread as it should appear in the logs
10
- char *name;
11
-
12
- // the section of netdata.conf to check if this is enabled or not
13
- char *config_section;
14
-
15
- // the name of the config option to check if it is true or false
16
- char *config_name;
17
-
18
- // the current status of the thread
19
- volatile sig_atomic_t enabled;
20
-
21
- // internal use, to maintain a pointer to the created thread
22
- netdata_thread_t *thread;
23
-
24
- // an initialization function to run before spawning the thread
25
- void (*init_routine) (void);
26
-
27
- // the threaded worker
28
- void *(*start_routine) (void *);
29
-
30
- // the environment variable to create
31
- char *env_name;
32
-
33
- // global variable
34
- bool *global_variable;
35
-};
36
-
37
-#define NETDATA_MAIN_THREAD_RUNNING CONFIG_BOOLEAN_YES
38
-#define NETDATA_MAIN_THREAD_EXITING (CONFIG_BOOLEAN_YES + 1)
39
-#define NETDATA_MAIN_THREAD_EXITED CONFIG_BOOLEAN_NO
40
-
8
extern const struct netdata_static_thread static_threads_common[];
9
extern const struct netdata_static_thread static_threads_linux[];
10
extern const struct netdata_static_thread static_threads_freebsd[];
libnetdata/dyn_conf/dyn_conf.c
+52
-12
@@ -20,10 +20,19 @@ struct deferred_cfg_send {
20
struct deferred_cfg_send *next;
21
};
22
23
+bool dyncfg_shutdown = false;
24
struct deferred_cfg_send *deferred_configs = NULL;
25
pthread_mutex_t deferred_configs_lock = PTHREAD_MUTEX_INITIALIZER;
26
pthread_cond_t deferred_configs_cond = PTHREAD_COND_INITIALIZER;
27
28
+static void deferred_config_free(struct deferred_cfg_send *dcs)
29
+{
30
+ freez(dcs->plugin_name);
31
+ freez(dcs->module_name);
32
+ freez(dcs->job_name);
33
+ freez(dcs);
34
+}
35
+
36
static void deferred_config_push_back(const char *plugin_name, const char *module_name, const char *job_name)
37
{
38
struct deferred_cfg_send *deferred = callocz(1, sizeof(struct deferred_cfg_send));
@@ -34,6 +43,11 @@ static void deferred_config_push_back(const char *plugin_name, const char *modul
43
deferred->job_name = strdupz(job_name);
44
}
45
pthread_mutex_lock(&deferred_configs_lock);
46
+ if (dyncfg_shutdown) {
47
+ pthread_mutex_unlock(&deferred_configs_lock);
48
+ deferred_config_free(deferred);
49
+ return;
50
+ }
51
struct deferred_cfg_send *last = deferred_configs;
52
if (last == NULL)
53
deferred_configs = deferred;
@@ -46,25 +60,29 @@ static void deferred_config_push_back(const char *plugin_name, const char *modul
60
pthread_mutex_unlock(&deferred_configs_lock);
61
}
62
49
-static struct deferred_cfg_send *deferred_config_pop()
63
+static void deferred_configs_unlock()
64
+{
65
+ dyncfg_shutdown = true;
66
+ // if we get cancelled in pthread_cond_wait
67
+ // we will arrive at cancelled cleanup handler
68
+ // with mutex locked we need to unlock it
69
+ pthread_mutex_unlock(&deferred_configs_lock);
70
+}
71
+
72
+static struct deferred_cfg_send *deferred_config_pop(void *ptr)
73
{
74
pthread_mutex_lock(&deferred_configs_lock);
52
- while (deferred_configs == NULL)
75
+ while (deferred_configs == NULL) {
76
+ netdata_thread_cleanup_push(deferred_configs_unlock, ptr);
77
pthread_cond_wait(&deferred_configs_cond, &deferred_configs_lock);
78
+ netdata_thread_cleanup_pop(0);
79
+ }
80
struct deferred_cfg_send *deferred = deferred_configs;
81
deferred_configs = deferred_configs->next;
82
pthread_mutex_unlock(&deferred_configs_lock);
83
return deferred;
84
}
85
60
-static void deferred_config_free(struct deferred_cfg_send *dcs)
61
-{
62
- freez(dcs->plugin_name);
63
- freez(dcs->module_name);
64
- freez(dcs->job_name);
65
- freez(dcs);
66
-}
67
-
86
static int _get_list_of_plugins_json_cb(const DICTIONARY_ITEM *item, void *entry, void *data)
87
{
88
UNUSED(item);
@@ -874,10 +892,30 @@ int dyn_conf_init(void)
892
return 0;
893
}
894
877
-void *dyncfg_main(void *in)
895
+static void dyncfg_cleanup(void *ptr) {
896
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *) ptr;
897
+ static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
898
+
899
+ netdata_log_info("cleaning up...");
900
+
901
+ pthread_mutex_lock(&deferred_configs_lock);
902
+ dyncfg_shutdown = true;
903
+ while (deferred_configs != NULL) {
904
+ struct deferred_cfg_send *dcs = deferred_configs;
905
+ deferred_configs = dcs->next;
906
+ deferred_config_free(dcs);
907
+ }
908
+ pthread_mutex_unlock(&deferred_configs_lock);
909
+
910
+ static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
911
+}
912
+
913
+void *dyncfg_main(void *ptr)
914
{
915
+ netdata_thread_cleanup_push(dyncfg_cleanup, ptr);
916
+
917
while (!netdata_exit) {
880
- struct deferred_cfg_send *dcs = deferred_config_pop();
918
+ struct deferred_cfg_send *dcs = deferred_config_pop(ptr);
919
const DICTIONARY_ITEM *plugin_item = dictionary_get_and_acquire_item(plugins_dict, dcs->plugin_name);
920
if (plugin_item == NULL) {
921
error_report("DYNCFG, plugin %s not found", dcs->plugin_name);
@@ -909,5 +947,7 @@ void *dyncfg_main(void *in)
947
deferred_config_free(dcs);
948
dictionary_acquired_item_release(plugins_dict, plugin_item);
949
}
950
+
951
+ netdata_thread_cleanup_pop(1);
952
return NULL;
953
}
libnetdata/threads/threads.h
+33
@@ -20,6 +20,39 @@ typedef enum {
20
21
typedef pthread_t netdata_thread_t;
22
23
+struct netdata_static_thread {
24
+ // the name of the thread as it should appear in the logs
25
+ char *name;
26
+
27
+ // the section of netdata.conf to check if this is enabled or not
28
+ char *config_section;
29
+
30
+ // the name of the config option to check if it is true or false
31
+ char *config_name;
32
+
33
+ // the current status of the thread
34
+ volatile sig_atomic_t enabled;
35
+
36
+ // internal use, to maintain a pointer to the created thread
37
+ netdata_thread_t *thread;
38
+
39
+ // an initialization function to run before spawning the thread
40
+ void (*init_routine) (void);
41
+
42
+ // the threaded worker
43
+ void *(*start_routine) (void *);
44
+
45
+ // the environment variable to create
46
+ char *env_name;
47
+
48
+ // global variable
49
+ bool *global_variable;
50
+};
51
+
52
+#define NETDATA_MAIN_THREAD_RUNNING CONFIG_BOOLEAN_YES
53
+#define NETDATA_MAIN_THREAD_EXITING (CONFIG_BOOLEAN_YES + 1)
54
+#define NETDATA_MAIN_THREAD_EXITED CONFIG_BOOLEAN_NO
55
+
56
#define NETDATA_THREAD_TAG_MAX 100
57
const char *netdata_thread_tag(void);
58
int netdata_thread_tag_exists(void);