improved netdata cleanup/exit procedure
Costa Tsaousis (ktsaou) committed
Jan 14, 2017 at 13:18 UTC
78c8a6bad687723c43930be4307b051af3977c22
16 files changed
+139
-82
src/backends.c
+3
-1
@@ -129,7 +129,7 @@ static inline int process_opentsdb_response(BUFFER *b) {
129
}
130
131
void *backends_main(void *ptr) {
132
- (void)ptr;
132
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
133
134
BUFFER *b = buffer_create(1), *response = buffer_create(1);
135
int (*backend_request_formatter)(BUFFER *b, const char *prefix, RRDHOST *host, const char *hostname, RRDSET *st, RRDDIM *rd, time_t after, time_t before, uint32_t options) = NULL;
@@ -543,6 +543,8 @@ cleanup:
543
544
info("BACKEND thread exiting");
545
546
+ static_thread->enabled = 0;
547
+ static_thread->thread = NULL;
548
pthread_exit(NULL);
549
return NULL;
550
}
src/health.c
+4
-1
@@ -2806,7 +2806,7 @@ static inline int rrdcalc_isrunnable(RRDCALC *rc, time_t now, time_t *next_run)
2806
}
2807
2808
void *health_main(void *ptr) {
2809
- (void)ptr;
2809
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
2810
2811
info("HEALTH thread created with task id %d", gettid());
2812
@@ -3113,6 +3113,9 @@ void *health_main(void *ptr) {
3113
buffer_free(wb);
3114
3115
info("HEALTH thread exiting");
3116
+
3117
+ static_thread->enabled = 0;
3118
+ static_thread->thread = NULL;
3119
pthread_exit(NULL);
3120
return NULL;
3121
}
src/main.c
+33
-29
@@ -9,6 +9,7 @@ void netdata_cleanup_and_exit(int ret) {
9
10
debug(D_EXIT, "Called: netdata_cleanup_and_exit()");
11
#ifdef NETDATA_INTERNAL_CHECKS
12
+ kill_childs();
13
rrdset_free_all();
14
#else
15
rrdset_save_all();
@@ -24,19 +25,7 @@ void netdata_cleanup_and_exit(int ret) {
25
exit(ret);
26
}
27
27
-struct netdata_static_thread {
28
- char *name;
29
-
30
- char *config_section;
31
- char *config_name;
32
-
33
- int enabled;
34
-
35
- pthread_t *thread;
36
-
37
- void (*init_routine) (void);
38
- void *(*start_routine) (void *);
39
-} static_threads[] = {
28
+struct netdata_static_thread static_threads[] = {
29
#ifdef INTERNAL_PLUGIN_NFACCT
30
// nfacct requires root access
31
// so, we build it as an external plugin with setuid to root
@@ -156,27 +145,32 @@ int killpid(pid_t pid, int sig)
145
146
void kill_childs()
147
{
148
+ error_log_limit_unlimited();
149
+
150
siginfo_t info;
151
152
struct web_client *w;
153
for(w = web_clients; w ; w = w->next) {
163
- debug(D_EXIT, "Stopping web client %s", w->client_ip);
154
+ info("Stopping web client %s", w->client_ip);
155
pthread_cancel(w->thread);
165
- pthread_join(w->thread, NULL);
156
+ // it is detached
157
+ // pthread_join(w->thread, NULL);
158
}
159
160
int i;
161
for (i = 0; static_threads[i].name != NULL ; i++) {
170
- if(static_threads[i].thread) {
171
- debug(D_EXIT, "Stopping %s thread", static_threads[i].name);
162
+ if(static_threads[i].enabled && static_threads[i].thread) {
163
+ info("Stopping %s thread", static_threads[i].name);
164
pthread_cancel(*static_threads[i].thread);
173
- pthread_join(*static_threads[i].thread, NULL);
165
+ // it is detached
166
+ // pthread_join(*static_threads[i].thread, NULL);
167
+
168
static_threads[i].thread = NULL;
169
}
170
}
171
172
if(tc_child_pid) {
179
- debug(D_EXIT, "Killing tc-qos-helper procees");
173
+ info("Killing tc-qos-helper process %d", tc_child_pid);
174
if(killpid(tc_child_pid, SIGTERM) != -1)
175
waitid(P_PID, (id_t) tc_child_pid, &info, WEXITED);
176
}
@@ -184,22 +178,32 @@ void kill_childs()
178
179
struct plugind *cd;
180
for(cd = pluginsd_root ; cd ; cd = cd->next) {
187
- debug(D_EXIT, "Stopping %s plugin thread", cd->id);
188
- pthread_cancel(cd->thread);
189
- pthread_join(cd->thread, NULL);
190
-
191
- if(cd->pid && !cd->obsolete) {
192
- debug(D_EXIT, "killing %s plugin process", cd->id);
193
- if(killpid(cd->pid, SIGTERM) != -1)
194
- waitid(P_PID, (id_t) cd->pid, &info, WEXITED);
181
+ if(!cd->obsolete) {
182
+ if(cd->thread) {
183
+ info("Stopping %s plugin thread", cd->id);
184
+ pthread_cancel(cd->thread);
185
+ // they are detached
186
+ // pthread_join(cd->thread, NULL);
187
+ }
188
+
189
+ if(cd->pid) {
190
+ info("killing %s plugin child process pid %d", cd->id, cd->pid);
191
+ if(killpid(cd->pid, SIGTERM) != -1)
192
+ waitid(P_PID, (id_t) cd->pid, &info, WEXITED);
193
+
194
+ cd->pid = 0;
195
+ }
196
+
197
+ cd->obsolete = 1;
198
}
199
}
200
201
// if, for any reason there is any child exited
202
// catch it here
203
+ info("Cleaning up an other children");
204
waitid(P_PID, 0, &info, WEXITED|WNOHANG);
205
202
- debug(D_EXIT, "All threads/childs stopped.");
206
+ info("All threads/childs stopped.");
207
}
208
209
struct option_def options[] = {
@@ -706,7 +710,7 @@ int main(int argc, char **argv)
710
711
debug(D_SYSTEM, "Starting thread %s.", st->name);
712
709
- if(pthread_create(st->thread, &attr, st->start_routine, NULL))
713
+ if(pthread_create(st->thread, &attr, st->start_routine, st))
714
error("failed to create new thread for %s.", st->name);
715
716
else if(pthread_detach(*st->thread))
src/main.h
+15
@@ -24,6 +24,21 @@ struct option_def {
24
*/
25
extern struct option_def options[];
26
27
+
28
+struct netdata_static_thread {
29
+ char *name;
30
+
31
+ char *config_section;
32
+ char *config_name;
33
+
34
+ volatile int enabled;
35
+
36
+ pthread_t *thread;
37
+
38
+ void (*init_routine) (void);
39
+ void *(*start_routine) (void *);
40
+};
41
+
42
extern void kill_childs(void);
43
extern int killpid(pid_t pid, int signal);
44
extern void netdata_cleanup_and_exit(int ret) NORETURN;
src/plugin_checks.c
+6
-3
@@ -1,8 +1,7 @@
1
#include "common.h"
2
3
-void *checks_main(void *ptr)
4
-{
5
- if(ptr) { ; }
3
+void *checks_main(void *ptr) {
4
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
5
6
info("CHECKS thread created with task id %d", gettid());
7
@@ -78,6 +77,10 @@ void *checks_main(void *ptr)
77
rrdset_done(check3);
78
}
79
80
+ info("CHECKS thread exiting");
81
+
82
+ static_thread->enabled = 0;
83
+ static_thread->thread = NULL;
84
pthread_exit(NULL);
85
return NULL;
86
}
src/plugin_freebsd.c
+4
-3
@@ -1,8 +1,7 @@
1
#include "common.h"
2
3
-void *freebsd_main(void *ptr)
4
-{
5
- (void)ptr;
3
+void *freebsd_main(void *ptr) {
4
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
5
6
info("FREEBSD Plugin thread created with task id %d", gettid());
7
@@ -59,6 +58,8 @@ void *freebsd_main(void *ptr)
58
59
info("FREEBSD thread exiting");
60
61
+ static_thread->enabled = 0;
62
+ static_thread->thread = NULL;
63
pthread_exit(NULL);
64
return NULL;
65
}
src/plugin_idlejitter.c
+7
-4
@@ -2,11 +2,10 @@
2
3
#define CPU_IDLEJITTER_SLEEP_TIME_MS 20
4
5
-void *cpuidlejitter_main(void *ptr)
6
-{
7
- if(ptr) { ; }
5
+void *cpuidlejitter_main(void *ptr) {
6
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
7
9
- info("CPU Idle Jitter thread created with task id %d", gettid());
8
+ info("IDLEJITTER thread created with task id %d", gettid());
9
10
if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
11
error("Cannot set pthread cancel type to DEFERRED.");
@@ -48,6 +47,10 @@ void *cpuidlejitter_main(void *ptr)
47
rrdset_done(st);
48
}
49
50
+ info("IDLEJITTER thread exiting");
51
+
52
+ static_thread->enabled = 0;
53
+ static_thread->thread = NULL;
54
pthread_exit(NULL);
55
return NULL;
56
}
src/plugin_macos.c
+4
-3
@@ -1,8 +1,7 @@
1
#include "common.h"
2
3
-void *macos_main(void *ptr)
4
-{
5
- (void)ptr;
3
+void *macos_main(void *ptr) {
4
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
5
6
info("MACOS Plugin thread created with task id %d", gettid());
7
@@ -79,6 +78,8 @@ void *macos_main(void *ptr)
78
79
info("MACOS thread exiting");
80
81
+ static_thread->enabled = 0;
82
+ static_thread->thread = NULL;
83
pthread_exit(NULL);
84
return NULL;
85
}
src/plugin_nfacct.c
+13
-14
@@ -55,7 +55,7 @@ static int nfacct_callback(const struct nlmsghdr *nlh, void *data) {
55
}
56
57
void *nfacct_main(void *ptr) {
58
- if(ptr) { ; }
58
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
59
60
info("NFACCT thread created with task id %d", gettid());
61
@@ -75,15 +75,12 @@ void *nfacct_main(void *ptr) {
75
nl = mnl_socket_open(NETLINK_NETFILTER);
76
if(!nl) {
77
error("nfacct.plugin: mnl_socket_open() failed");
78
- pthread_exit(NULL);
79
- return NULL;
78
+ goto cleanup;
79
}
80
81
if(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
83
- mnl_socket_close(nl);
82
error("nfacct.plugin: mnl_socket_bind() failed");
85
- pthread_exit(NULL);
86
- return NULL;
83
+ goto cleanup;
84
}
85
portid = mnl_socket_get_portid(nl);
86
@@ -104,16 +101,13 @@ void *nfacct_main(void *ptr) {
101
102
nlh = nfacct_nlmsg_build_hdr(buf, NFNL_MSG_ACCT_GET, NLM_F_DUMP, seq);
103
if(!nlh) {
107
- mnl_socket_close(nl);
104
error("nfacct.plugin: nfacct_nlmsg_build_hdr() failed");
109
- pthread_exit(NULL);
110
- return NULL;
105
+ goto cleanup;
106
}
107
108
if(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
109
error("nfacct.plugin: mnl_socket_send");
115
- pthread_exit(NULL);
116
- return NULL;
110
+ goto cleanup;
111
}
112
113
if(nfacct_list) nfacct_list->len = 0;
@@ -125,8 +119,7 @@ void *nfacct_main(void *ptr) {
119
120
if (ret == -1) {
121
error("nfacct.plugin: error communicating with kernel.");
128
- pthread_exit(NULL);
129
- return NULL;
122
+ goto cleanup;
123
}
124
125
// --------------------------------------------------------------------
@@ -191,7 +184,13 @@ void *nfacct_main(void *ptr) {
184
memmove(&last, &now, sizeof(struct timeval));
185
}
186
194
- mnl_socket_close(nl);
187
+cleanup:
188
+ info("NFACCT thread exiting");
189
+
190
+ if(nl) mnl_socket_close(nl);
191
+
192
+ static_thread->enabled = 0;
193
+ static_thread->thread = NULL;
194
pthread_exit(NULL);
195
return NULL;
196
}
src/plugin_proc.c
+4
-3
@@ -56,9 +56,8 @@ static struct proc_module {
56
{ .name = NULL, .dim = NULL, .func = NULL }
57
};
58
59
-void *proc_main(void *ptr)
60
-{
61
- (void)ptr;
59
+void *proc_main(void *ptr) {
60
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
61
62
info("PROC Plugin thread created with task id %d", gettid());
63
@@ -140,6 +139,8 @@ void *proc_main(void *ptr)
139
140
info("PROC thread exiting");
141
142
+ static_thread->enabled = 0;
143
+ static_thread->thread = NULL;
144
pthread_exit(NULL);
145
return NULL;
146
}
src/plugin_tc.c
+9
-7
@@ -749,7 +749,7 @@ static inline void tc_split_words(char *str, char **words, int max_words) {
749
750
pid_t tc_child_pid = 0;
751
void *tc_main(void *ptr) {
752
- (void)ptr;
752
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
753
754
info("TC thread created with task id %d", gettid());
755
@@ -796,8 +796,7 @@ void *tc_main(void *ptr) {
796
fp = mypopen(buffer, &tc_child_pid);
797
if(unlikely(!fp)) {
798
error("TC: Cannot popen(\"%s\", \"r\").", buffer);
799
- pthread_exit(NULL);
800
- return NULL;
799
+ goto cleanup;
800
}
801
802
while(fgets(buffer, TC_LINE_MAX, fp) != NULL) {
@@ -998,8 +997,7 @@ void *tc_main(void *ptr) {
997
998
if(unlikely(netdata_exit)) {
999
tc_device_free_all();
1001
- pthread_exit(NULL);
1002
- return NULL;
1000
+ goto cleanup;
1001
}
1002
1003
if(code == 1 || code == 127) {
@@ -1008,13 +1006,17 @@ void *tc_main(void *ptr) {
1006
error("TC: tc-qos-helper.sh exited with code %d. Disabling it.", code);
1007
1008
tc_device_free_all();
1011
- pthread_exit(NULL);
1012
- return NULL;
1009
+ goto cleanup;
1010
}
1011
1012
sleep((unsigned int) rrd_update_every);
1013
}
1014
1015
+cleanup:
1016
+ info("TC thread exiting");
1017
+
1018
+ static_thread->enabled = 0;
1019
+ static_thread->thread = NULL;
1020
pthread_exit(NULL);
1021
return NULL;
1022
}
src/plugins_d.c
+11
-4
@@ -428,12 +428,13 @@ void *pluginsd_worker_thread(void *arg)
428
info("PLUGINSD: '%s' thread exiting", cd->fullfilename);
429
430
cd->obsolete = 1;
431
+ cd->thread = 0;
432
pthread_exit(NULL);
433
return NULL;
434
}
435
436
void *pluginsd_main(void *ptr) {
436
- (void)ptr;
437
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
438
439
info("PLUGINS.D thread created with task id %d", gettid());
440
@@ -461,8 +462,7 @@ void *pluginsd_main(void *ptr) {
462
dir = opendir(dir_name);
463
if(unlikely(!dir)) {
464
error("Cannot open directory '%s'.", dir_name);
464
- pthread_exit(NULL);
465
- return NULL;
465
+ goto cleanup;
466
}
467
468
while(likely((file = readdir(dir)))) {
@@ -520,7 +520,10 @@ void *pluginsd_main(void *ptr) {
520
}
521
cd->obsolete = 0;
522
523
- if(unlikely(!cd->enabled)) continue;
523
+ if(unlikely(!cd->enabled)) {
524
+ cd->obsolete = 1;
525
+ continue;
526
+ }
527
528
// spawn a new thread for it
529
if(unlikely(pthread_create(&cd->thread, NULL, pluginsd_worker_thread, cd) != 0)) {
@@ -529,14 +532,18 @@ void *pluginsd_main(void *ptr) {
532
}
533
else if(unlikely(pthread_detach(cd->thread) != 0))
534
error("PLUGINSD: Cannot request detach of newly created thread for plugin '%s'.", cd->filename);
535
+
536
}
537
538
closedir(dir);
539
sleep((unsigned int) scan_frequency);
540
}
541
542
+cleanup:
543
info("PLUGINS.D thread exiting");
544
545
+ static_thread->enabled = 0;
546
+ static_thread->thread = NULL;
547
pthread_exit(NULL);
548
return NULL;
549
}
src/plugins_d.h
+1
-1
@@ -23,7 +23,7 @@ struct plugind {
23
// without collecting values
24
25
int update_every; // the plugin default data collection frequency
26
- int obsolete; // do not touch this structure after setting this to 1
26
+ volatile int obsolete; // do not touch this structure after setting this to 1
27
int enabled; // if this is enabled or not
28
29
time_t started_t;
src/rrd.c
+12
-4
@@ -648,18 +648,26 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
648
649
RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier, long divisor, int algorithm)
650
{
651
+ RRDDIM *rd = rrddim_find(st, id);
652
+ if(rd) {
653
+ error("Cannot create rrd dimension '%s/%s', it already exists.", st->id, name);
654
+ return rd;
655
+ }
656
+
657
char filename[FILENAME_MAX + 1];
658
char fullfilename[FILENAME_MAX + 1];
659
660
char varname[CONFIG_MAX_NAME + 1];
655
- RRDDIM *rd = NULL;
661
unsigned long size = sizeof(RRDDIM) + (st->entries * sizeof(storage_number));
662
663
debug(D_RRD_CALLS, "Adding dimension '%s/%s'.", st->id, id);
664
665
rrdset_strncpyz_name(filename, id, FILENAME_MAX);
666
snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
662
- if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
667
+
668
+ if(rrd_memory_mode != RRD_MEMORY_MODE_RAM)
669
+ rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
670
+
671
if(rd) {
672
struct timeval now;
673
now_realtime_timeval(&now);
@@ -901,9 +909,9 @@ void rrdset_save_all(void) {
909
RRDSET *st;
910
RRDDIM *rd;
911
904
- rrdhost_rwlock(&localhost);
912
+ rrdhost_rdlock(&localhost);
913
for(st = localhost.rrdset_root; st ; st = st->next) {
906
- pthread_rwlock_wrlock(&st->rwlock);
914
+ pthread_rwlock_rdlock(&st->rwlock);
915
916
if(st->mapped == RRD_MEMORY_MODE_SAVE) {
917
debug(D_RRD_CALLS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
src/sys_fs_cgroup.c
+4
-3
@@ -1427,9 +1427,8 @@ int do_sys_fs_cgroup(int update_every, usec_t dt) {
1427
return 0;
1428
}
1429
1430
-void *cgroups_main(void *ptr)
1431
-{
1432
- (void)ptr;
1430
+void *cgroups_main(void *ptr) {
1431
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
1432
1433
info("CGROUP Plugin thread created with task id %d", gettid());
1434
@@ -1501,6 +1500,8 @@ void *cgroups_main(void *ptr)
1500
1501
info("CGROUP thread exiting");
1502
1503
+ static_thread->enabled = 0;
1504
+ static_thread->thread = NULL;
1505
pthread_exit(NULL);
1506
return NULL;
1507
}
src/web_server.c
+9
-2
@@ -390,7 +390,7 @@ static inline void cleanup_web_clients(void) {
390
#define CLEANUP_EVERY_EVENTS 100
391
392
void *socket_listen_main_multi_threaded(void *ptr) {
393
- (void)ptr;
393
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
394
395
web_server_mode = WEB_SERVER_MODE_MULTI_THREADED;
396
info("Multi-threaded WEB SERVER thread created with task id %d", gettid());
@@ -470,6 +470,9 @@ void *socket_listen_main_multi_threaded(void *ptr) {
470
debug(D_WEB_CLIENT, "LISTENER: exit!");
471
close_listen_sockets();
472
473
+ static_thread->enabled = 0;
474
+ static_thread->thread = NULL;
475
+ pthread_exit(NULL);
476
return NULL;
477
}
478
@@ -518,7 +521,7 @@ static inline int single_threaded_unlink_client(struct web_client *w, fd_set *if
521
}
522
523
void *socket_listen_main_single_threaded(void *ptr) {
521
- (void)ptr;
524
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
525
526
web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED;
527
@@ -637,5 +640,9 @@ void *socket_listen_main_single_threaded(void *ptr) {
640
641
debug(D_WEB_CLIENT, "LISTENER: exit!");
642
close_listen_sockets();
643
+
644
+ static_thread->enabled = 0;
645
+ static_thread->thread = NULL;
646
+ pthread_exit(NULL);
647
return NULL;
648
}