properly cleanup all threads on exit
Costa Tsaousis (ktsaou) committed
May 20, 2014 at 01:58 UTC
adcc8e8a6906c8e1955e71d37d9c5a3c5c5b9b5a
1 file changed
+128
-25
netdata.c
+128
-25
@@ -1686,6 +1686,10 @@ void rrd_stats_next_plugins(RRD_STATS *st)
1686
unsigned long long rrd_stats_done(RRD_STATS *st)
1687
{
1688
RRD_DIMENSION *rd, *last;
1689
+ int oldstate;
1690
+
1691
+ if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)
1692
+ error("Cannot set pthread cancel state to DISABLE.");
1693
1694
// a read lock is OK here
1695
pthread_rwlock_rdlock(&st->rwlock);
@@ -1705,6 +1709,10 @@ unsigned long long rrd_stats_done(RRD_STATS *st)
1709
if(st->debug) debug(D_RRD_STATS, "%s: Skipping collected values (usec since last update = %llu, counter_done = %lu)", st->name, st->usec_since_last_update, st->counter_done);
1710
// we don't have any usable data yet
1711
pthread_rwlock_unlock(&st->rwlock);
1712
+
1713
+ if(pthread_setcancelstate(oldstate, NULL) != 0)
1714
+ error("Cannot set pthread cancel state to RESTORE (%d).", oldstate);
1715
+
1716
return(st->usec_since_last_update);
1717
}
1718
@@ -1973,6 +1981,10 @@ unsigned long long rrd_stats_done(RRD_STATS *st)
1981
}
1982
1983
pthread_rwlock_unlock(&st->rwlock);
1984
+
1985
+ if(pthread_setcancelstate(oldstate, NULL) != 0)
1986
+ error("Cannot set pthread cancel state to RESTORE (%d).", oldstate);
1987
+
1988
return(st->usec_since_last_update);
1989
}
1990
@@ -3785,6 +3797,12 @@ long web_client_receive(struct web_client *w)
3797
3798
void *new_client(void *ptr)
3799
{
3800
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
3801
+ error("Cannot set pthread cancel type to DEFERRED.");
3802
+
3803
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
3804
+ error("Cannot set pthread cancel state to ENABLE.");
3805
+
3806
struct timeval tv;
3807
struct web_client *w = ptr;
3808
int retval;
@@ -5835,6 +5853,13 @@ int do_proc_vmstat() {
5853
void *proc_main(void *ptr)
5854
{
5855
if(ptr) { ; }
5856
+
5857
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
5858
+ error("Cannot set pthread cancel type to DEFERRED.");
5859
+
5860
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
5861
+ error("Cannot set pthread cancel state to ENABLE.");
5862
+
5863
struct rusage me, me_last;
5864
struct timeval last, now;
5865
@@ -6149,6 +6174,13 @@ pid_t tc_child_pid = 0;
6174
void *tc_main(void *ptr)
6175
{
6176
if(ptr) { ; }
6177
+
6178
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
6179
+ error("Cannot set pthread cancel type to DEFERRED.");
6180
+
6181
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
6182
+ error("Cannot set pthread cancel state to ENABLE.");
6183
+
6184
char buffer[TC_LINE_MAX+1] = "";
6185
6186
for(;1;) {
@@ -6176,10 +6208,16 @@ void *tc_main(void *ptr)
6208
6209
if(strcmp(p, "END") == 0) {
6210
if(device) {
6211
+ if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0)
6212
+ error("Cannot set pthread cancel state to DISABLE.");
6213
+
6214
tc_device_commit(device);
6215
tc_device_free(device);
6216
device = NULL;
6217
class = NULL;
6218
+
6219
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
6220
+ error("Cannot set pthread cancel state to ENABLE.");
6221
}
6222
}
6223
else if(strcmp(p, "BEGIN") == 0) {
@@ -6278,15 +6316,28 @@ void *tc_main(void *ptr)
6316
void *cpuidlejitter_main(void *ptr)
6317
{
6318
if(ptr) { ; }
6319
+
6320
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
6321
+ error("Cannot set pthread cancel type to DEFERRED.");
6322
+
6323
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
6324
+ error("Cannot set pthread cancel state to ENABLE.");
6325
+
6326
int sleep_ms = config_get_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
6327
if(sleep_ms <= 0) {
6328
config_set_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
6329
sleep_ms = CPU_IDLEJITTER_SLEEP_TIME_MS;
6330
}
6331
6287
- struct timeval before, after;
6332
+ RRD_STATS *st = rrd_stats_find("system.idlejitter");
6333
+ if(!st) {
6334
+ st = rrd_stats_create("system", "idlejitter", NULL, "cpu", "CPU Idle Jitter", "microseconds lost/s", 9999, update_every, CHART_TYPE_LINE);
6335
+ rrd_stats_dimension_add(st, "jitter", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
6336
+ }
6337
6289
- while(1) {
6338
+ struct timeval before, after;
6339
+ unsigned long long counter;
6340
+ for(counter = 0; 1 ;counter++) {
6341
unsigned long long usec = 0, susec = 0;
6342
6343
while(susec < (update_every * 1000000ULL)) {
@@ -6301,14 +6352,7 @@ void *cpuidlejitter_main(void *ptr)
6352
}
6353
usec -= (sleep_ms * 1000);
6354
6304
- RRD_STATS *st = rrd_stats_find("system.idlejitter");
6305
- if(!st) {
6306
- st = rrd_stats_create("system", "idlejitter", NULL, "cpu", "CPU Idle Jitter", "microseconds lost/s", 9999, update_every, CHART_TYPE_LINE);
6307
-
6308
- rrd_stats_dimension_add(st, "jitter", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
6309
- }
6310
- else rrd_stats_next_usec(st, susec);
6311
-
6355
+ if(counter) rrd_stats_next_usec(st, susec);
6356
rrd_stats_dimension_set(st, "jitter", usec);
6357
rrd_stats_done(st);
6358
}
@@ -6322,6 +6366,13 @@ void *cpuidlejitter_main(void *ptr)
6366
void *checks_main(void *ptr)
6367
{
6368
if(ptr) { ; }
6369
+
6370
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
6371
+ error("Cannot set pthread cancel type to DEFERRED.");
6372
+
6373
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
6374
+ error("Cannot set pthread cancel state to ENABLE.");
6375
+
6376
unsigned long long usec = 0, susec = update_every * 1000000ULL, loop_usec = 0, total_susec = 0;
6377
struct timeval now, last, loop;
6378
@@ -6724,6 +6775,13 @@ void *pluginsd_worker_thread(void *arg)
6775
void *pluginsd_main(void *ptr)
6776
{
6777
if(ptr) { ; }
6778
+
6779
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
6780
+ error("Cannot set pthread cancel type to DEFERRED.");
6781
+
6782
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
6783
+ error("Cannot set pthread cancel state to ENABLE.");
6784
+
6785
char *dir_name = config_get("plugins", "plugins directory", PLUGINS_DIR);
6786
int automatic_run = config_get_boolean("plugins", "enable running new plugins", 0);
6787
int scan_frequency = config_get_number("plugins", "check for new plugins every", 60);
@@ -6819,17 +6877,59 @@ void *pluginsd_main(void *ptr)
6877
// ----------------------------------------------------------------------------
6878
// main and related functions
6879
6880
+pthread_t *p_proc = NULL, *p_tc = NULL, *p_jitter = NULL, *p_pluginsd = NULL, *p_checks = NULL;
6881
+
6882
void kill_childs()
6883
{
6884
+ if(p_proc) {
6885
+ pthread_cancel(*p_proc);
6886
+ pthread_join(*p_proc, NULL);
6887
+ p_proc = NULL;
6888
+ }
6889
+
6890
+ if(p_jitter) {
6891
+ pthread_cancel(*p_jitter);
6892
+ pthread_join(*p_jitter, NULL);
6893
+ p_jitter = NULL;
6894
+ }
6895
+
6896
+ if(p_checks) {
6897
+ pthread_cancel(*p_checks);
6898
+ pthread_join(*p_checks, NULL);
6899
+ p_checks = NULL;
6900
+ }
6901
+
6902
if(tc_child_pid) kill(tc_child_pid, SIGTERM);
6903
tc_child_pid = 0;
6904
6905
+ if(p_tc) {
6906
+ pthread_cancel(*p_tc);
6907
+ pthread_join(*p_tc, NULL);
6908
+ p_tc = NULL;
6909
+ }
6910
+
6911
+ if(p_pluginsd) {
6912
+ pthread_cancel(*p_pluginsd);
6913
+ pthread_join(*p_pluginsd, NULL);
6914
+ p_pluginsd = NULL;
6915
+ }
6916
+
6917
struct plugind *cd;
6828
- for(cd = pluginsd_root ; cd ; cd = cd->next)
6918
+ for(cd = pluginsd_root ; cd ; cd = cd->next) {
6919
if(cd->pid && !cd->obsolete) {
6920
kill(cd->pid, SIGTERM);
6921
cd->pid = 0;
6922
}
6923
+
6924
+ pthread_cancel(cd->thread);
6925
+ pthread_join(cd->thread, NULL);
6926
+ }
6927
+
6928
+ struct web_client *w;
6929
+ for(w = web_clients; w ; w = w->next) {
6930
+ pthread_cancel(w->thread);
6931
+ pthread_join(w->thread, NULL);
6932
+ }
6933
}
6934
6935
void sig_handler(int signo)
@@ -6842,8 +6942,9 @@ void sig_handler(int signo)
6942
case SIGFPE:
6943
case SIGSEGV:
6944
error("Signaled exit (signal %d). Errno: %d (%s)", signo, errno, strerror(errno));
6945
+ signal(signo, SIG_IGN);
6946
kill_childs();
6846
- rrd_stats_save_all();
6947
+ rrd_stats_free_all();
6948
exit(1);
6949
break;
6950
@@ -7253,40 +7354,42 @@ int main(int argc, char **argv)
7354
// catch all signals
7355
for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV && i != SIGFPE) signal(i, sig_handler);
7356
7256
-
7257
- pthread_t p_proc, p_tc, p_jitter, p_pluginsd, p_checks;
7258
-
7357
// spawn childs to collect data
7358
if(config_get_boolean("plugins", "tc", 1)) {
7261
- if(pthread_create(&p_tc, NULL, tc_main, NULL))
7359
+ p_tc = malloc(sizeof(pthread_t));
7360
+ if(pthread_create(p_tc, NULL, tc_main, NULL))
7361
error("failed to create new thread for tc.");
7263
- else if(pthread_detach(p_tc))
7362
+ else if(pthread_detach(*p_tc))
7363
error("Cannot request detach of newly created tc thread.");
7364
}
7365
7366
if(config_get_boolean("plugins", "idlejitter", 1)) {
7268
- if(pthread_create(&p_jitter, NULL, cpuidlejitter_main, NULL))
7367
+ p_jitter = malloc(sizeof(pthread_t));
7368
+ if(pthread_create(p_jitter, NULL, cpuidlejitter_main, NULL))
7369
error("failed to create new thread for idlejitter.");
7270
- else if(pthread_detach(p_jitter))
7370
+ else if(pthread_detach(*p_jitter))
7371
error("Cannot request detach of newly created idlejitter thread.");
7372
}
7373
7374
if(config_get_boolean("plugins", "proc", 1)) {
7275
- if(pthread_create(&p_proc, NULL, proc_main, NULL))
7375
+ p_proc = malloc(sizeof(pthread_t));
7376
+ if(pthread_create(p_proc, NULL, proc_main, NULL))
7377
error("failed to create new thread for proc.");
7277
- else if(pthread_detach(p_proc))
7378
+ else if(pthread_detach(*p_proc))
7379
error("Cannot request detach of newly created proc thread.");
7380
}
7381
7281
- if(pthread_create(&p_pluginsd, NULL, pluginsd_main, NULL))
7382
+ p_pluginsd = malloc(sizeof(pthread_t));
7383
+ if(pthread_create(p_pluginsd, NULL, pluginsd_main, NULL))
7384
error("failed to create new thread for plugins.d.");
7283
- else if(pthread_detach(p_pluginsd))
7385
+ else if(pthread_detach(*p_pluginsd))
7386
error("Cannot request detach of newly created plugins.d thread.");
7387
7388
if(config_get_boolean("plugins", "checks", 1)) {
7287
- if(pthread_create(&p_checks, NULL, checks_main, NULL))
7389
+ p_checks = malloc(sizeof(pthread_t));
7390
+ if(pthread_create(p_checks, NULL, checks_main, NULL))
7391
error("failed to create new thread for checks.");
7289
- else if(pthread_detach(p_checks))
7392
+ else if(pthread_detach(*p_checks))
7393
error("Cannot request detach of newly created checks thread.");
7394
}
7395