@cryptotaxi247 / netdata-1 / commits / 78c8a6bad

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 }