fixed all crashes; empty responses are now formatted properly; fixed exit procedure to exit successfully; solved thread unsafety of localtime(); make all .js files cacheable and all .json files not cacheable
Costa Tsaousis (ktsaou) committed
Dec 7, 2015 at 22:42 UTC
e29c2bd77507c137a9e3524c3d8dcbddff1983d8
6 files changed
+88
-51
src/log.c
+4
-2
@@ -32,10 +32,10 @@ void log_date(FILE *out)
32
{
33
char outstr[200];
34
time_t t;
35
- struct tm *tmp;
35
+ struct tm *tmp, tmbuf;
36
37
t = time(NULL);
38
- tmp = localtime(&t);
38
+ tmp = localtime_r(&t, &tmbuf);
39
40
if (tmp == NULL) return;
41
if (strftime(outstr, sizeof(outstr), "%y-%m-%d %H:%M:%S", tmp) == 0) return;
@@ -142,7 +142,9 @@ void log_access( const char *fmt, ... )
142
vfprintf( stdaccess, fmt, args );
143
va_end( args );
144
fprintf( stdaccess, "\n");
145
+#ifdef NETDATA_INTERNAL_CHECKS
146
fflush( stdaccess );
147
+#endif
148
}
149
150
if(access_log_syslog) {
src/main.c
+6
-2
@@ -157,7 +157,7 @@ void kill_childs()
157
if(tc_child_pid) {
158
info("Killing tc-qos-helper procees");
159
if(killpid(tc_child_pid, SIGTERM) != -1)
160
- waitid(tc_child_pid, 0, &info, WEXITED);
160
+ waitid(P_PID, tc_child_pid, &info, WEXITED);
161
}
162
tc_child_pid = 0;
163
@@ -170,10 +170,14 @@ void kill_childs()
170
if(cd->pid && !cd->obsolete) {
171
debug(D_EXIT, "killing %s plugin process", cd->id);
172
if(killpid(cd->pid, SIGTERM) != -1)
173
- waitid(cd->pid, 0, &info, WEXITED);
173
+ waitid(P_PID, cd->pid, &info, WEXITED);
174
}
175
}
176
177
+ // if, for any reason there is any child exited
178
+ // catch it here
179
+ waitid(P_PID, 0, &info, WEXITED|WNOHANG);
180
+
181
debug(D_EXIT, "All threads/childs stopped.");
182
}
183
src/rrd2json.c
+26
-30
@@ -427,6 +427,7 @@ void rrdr_buffer_print_format(BUFFER *wb, uint32_t format)
427
428
void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
429
{
430
+ //info("JSONWRAPPER(): %s: BEGIN", r->st->id);
431
char kq[2] = "", // key quote
432
sq[2] = ""; // string quote
433
@@ -511,6 +512,7 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
512
);
513
514
if(string_value) buffer_strcat(wb, sq);
515
+ //info("JSONWRAPPER(): %s: END", r->st->id);
516
}
517
518
void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
@@ -534,6 +536,7 @@ void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t option
536
537
static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
538
{
539
+ //info("RRD2JSON(): %s: BEGIN", r->st->id);
540
int row_annotations = 0, dates = JSON_DATES_JS, dates_with_new = 0;
541
char kq[2] = "", // key quote
542
sq[2] = "", // string quote
@@ -639,12 +642,8 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
642
643
// if all dimensions are hidden, print a null
644
if(!i) {
642
- buffer_strcat(wb, pre_value);
643
- if(options & RRDR_OPTION_NULL2ZERO)
644
- buffer_strcat(wb, "0");
645
- else
646
- buffer_strcat(wb, "null");
647
- buffer_strcat(wb, post_value);
645
+ buffer_strcat(wb, finish);
646
+ return;
647
}
648
649
long start = 0, end = rrdr_rows(r), step = 1;
@@ -663,8 +662,8 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
662
663
if(dates == JSON_DATES_JS) {
664
// generate the local date time
666
- struct tm *tm = localtime(&now);
667
- if(!tm) { error("localtime() failed."); continue; }
665
+ struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
666
+ if(!tm) { error("localtime_r() failed."); continue; }
667
668
if(likely(i != start)) buffer_strcat(wb, ",\n");
669
buffer_strcat(wb, pre_date);
@@ -738,10 +737,12 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
737
}
738
739
buffer_strcat(wb, finish);
740
+ //info("RRD2JSON(): %s: END", r->st->id);
741
}
742
743
static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startline, const char *separator, const char *endline)
744
{
745
+ //info("RRD2CSV(): %s: BEGIN", r->st->id);
746
long c, i;
747
RRDDIM *d;
748
@@ -789,7 +790,7 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
790
}
791
else {
792
// generate the local date time
792
- struct tm *tm = localtime(&now);
793
+ struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
794
if(!tm) { error("localtime() failed."); continue; }
795
buffer_date(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
796
}
@@ -817,10 +818,12 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
818
819
buffer_strcat(wb, endline);
820
}
821
+ //info("RRD2CSV(): %s: END", r->st->id);
822
}
823
824
static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix, const char *separator, const char *suffix)
825
{
826
+ //info("RRD2SSV(): %s: BEGIN", r->st->id);
827
long c, i;
828
RRDDIM *d;
829
@@ -885,6 +888,7 @@ static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix,
888
buffer_rrd_value(wb, sum);
889
}
890
buffer_strcat(wb, suffix);
891
+ //info("RRD2SSV(): %s: END", r->st->id);
892
}
893
894
inline static calculated_number *rrdr_line_values(RRDR *r)
@@ -962,11 +966,10 @@ static RRDR *rrdr_create(RRDSET *st, int n)
966
return NULL;
967
}
968
965
- RRDR *r = malloc(sizeof(RRDR));
969
+ RRDR *r = calloc(1, sizeof(RRDR));
970
if(unlikely(!r)) goto cleanup;
971
972
r->st = st;
969
- r->has_st_lock = 0;
973
974
rrdr_lock_rrdset(r);
975
@@ -988,17 +991,10 @@ static RRDR *rrdr_create(RRDSET *st, int n)
991
if(unlikely(!r->od)) goto cleanup;
992
993
r->c = -1;
991
- r->rows = 0;
994
995
r->group = 1;
996
r->update_every = 1;
997
996
- r->min = 0.0;
997
- r->max = 0.0;
998
-
999
- r->before = 0;
1000
- r->after = 0;
1001
-
998
return r;
999
1000
cleanup:
@@ -1042,11 +1038,11 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1038
1039
// the duration of the chart
1040
time_t duration = before - after;
1045
- if(duration <= 0) return NULL;
1046
-
1047
- // how many points does the chart has?
1041
long available_points = duration / st->update_every;
1042
1043
+ if(duration <= 0 || available_points <= 0)
1044
+ return rrdr_create(st, 1);
1045
+
1046
// check the wanted points
1047
if(points < 0) points = -points;
1048
if(points > available_points) points = available_points;
@@ -1067,6 +1063,7 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1063
long start_at_slot = rrdset_time2slot(st, before_new),
1064
stop_at_slot = rrdset_time2slot(st, after_new);
1065
1066
+#ifdef NETDATA_INTERNAL_CHECKS
1067
if(after_new < first_entry_t) {
1068
error("after_new %u is too small, minimum %u", after_new, first_entry_t);
1069
}
@@ -1081,17 +1078,16 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1078
}
1079
if(start_at_slot < 0 || start_at_slot >= st->entries) {
1080
error("start_at_slot is invalid %ld, expected %ld to %ld", start_at_slot, 0, st->entries - 1);
1084
- start_at_slot = st->current_entry;
1081
}
1082
if(stop_at_slot < 0 || stop_at_slot >= st->entries) {
1083
error("stop_at_slot is invalid %ld, expected %ld to %ld", stop_at_slot, 0, st->entries - 1);
1088
- stop_at_slot = 0;
1084
}
1085
if(points_new > (before_new - after_new) / group / st->update_every + 1) {
1086
error("points_new %ld is more than points %ld", points_new, (before_new - after_new) / group / st->update_every + 1);
1087
}
1088
+#endif
1089
1094
- // error("SHIFT: %s: wanted %ld points, got %ld - group=%ld, wanted duration=%u, got %u - wanted %ld - %ld, got %ld - %ld", st->id, points, points_new, group, before - after, before_new - after_new, after, before, after_new, before_new);
1090
+ //info("RRD2RRDR(): %s: wanted %ld points, got %ld - group=%ld, wanted duration=%u, got %u - wanted %ld - %ld, got %ld - %ld", st->id, points, points_new, group, before - after, before_new - after_new, after, before, after_new, before_new);
1091
1092
after = after_new;
1093
before = before_new;
@@ -1112,10 +1108,7 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1108
1109
RRDR *r = rrdr_create(st, points);
1110
if(!r) return NULL;
1115
- if(!r->d) {
1116
- rrdr_free(r);
1117
- return NULL;
1118
- }
1111
+ if(!r->d) return r;
1112
1113
// find how many dimensions we have
1114
long dimensions = r->d;
@@ -1180,6 +1173,8 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1173
r->before = now;
1174
r->after = now;
1175
1176
+ //info("RRD2RRDR(): %s: STARTING", st->id);
1177
+
1178
long slot = start_at_slot, counter = 0, stop_now = 0, added = 0, group_count = 0, add_this = 0;
1179
for(; !stop_now ; now -= dt, slot--, counter++) {
1180
if(unlikely(slot < 0)) slot = st->entries - 1;
@@ -1211,7 +1206,7 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1206
}
1207
1208
// do the calculations
1214
- for(rd = st->dimensions, c = 0 ; likely(rd && c < dimensions) ; rd = rd->next, c++) {
1209
+ for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1210
storage_number n = rd->values[slot];
1211
if(unlikely(!does_storage_number_exist(n))) continue;
1212
@@ -1286,6 +1281,7 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1281
}
1282
1283
rrdr_done(r);
1284
+ //info("RRD2RRDR(): %s: END %ld loops made, %ld points generated", st->id, counter, rrdr_rows(r));
1285
//error("SHIFT: %s: wanted %ld points, got %ld", st->id, points, rrdr_rows(r));
1286
return r;
1287
}
@@ -1650,7 +1646,7 @@ unsigned long rrd_stats_json(int type, RRDSET *st, BUFFER *wb, int points, int g
1646
}
1647
1648
// generate the local date time
1653
- struct tm *tm = localtime(&now);
1649
+ struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
1650
if(!tm) { error("localtime() failed."); continue; }
1651
if(now > last_timestamp) last_timestamp = now;
1652
src/web_buffer.c
+4
@@ -20,7 +20,11 @@ static inline void buffer_overflow_init(BUFFER *b)
20
strcpy(&b->buffer[b->size + 1], BUFFER_OVERFLOW_EOF);
21
}
22
23
+#ifdef NETDATA_INTERNAL_CHECKS
24
#define buffer_overflow_check(b) _buffer_overflow_check(b, __FILE__, __FUNCTION__, __LINE__)
25
+#else
26
+#define buffer_overflow_check(b)
27
+#endif
28
29
static inline void _buffer_overflow_check(BUFFER *b, const char *file, const char *function, const unsigned long line)
30
{
src/web_client.c
+5
-5
@@ -527,10 +527,10 @@ int web_client_api_request_v1_chart(struct web_client *w, char *url)
527
// they are not null and not empty
528
529
if(!strcmp(name, "chart")) chart = value;
530
- else {
531
- buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
532
- goto cleanup;
533
- }
530
+ //else {
531
+ /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
532
+ // goto cleanup;
533
+ //}
534
}
535
536
if(!chart || !*chart) {
@@ -1009,7 +1009,7 @@ void web_client_process(struct web_client *w) {
1009
datasource_type = DATASOURCE_JSON;
1010
code = web_client_api_request(w, url);
1011
}
1012
-#ifdef WEB_EXIT
1012
+#ifdef NETDATA_INTERNAL_CHECKS
1013
else if(strcmp(tok, "exit") == 0) {
1014
netdata_exit = 1;
1015
code = 200;
web/dashboard.js
+43
-12
@@ -383,7 +383,7 @@
383
element_chart_id: null,
384
element_legend: null, // the element with the legend of the chart (if created by us)
385
element_legend_id: null,
386
-
386
+
387
chart_url: null, // string - the url to download chart info
388
chart: null, // object - the chart as downloaded from the server
389
@@ -885,7 +885,7 @@
885
this.library.initialize(function() { this_state_object.updateChart(callback); });
886
return;
887
}
888
-
888
+
889
this.clearSelection();
890
this.chartURL();
891
if(this.debug) this.log('updating from ' + this.current.url);
@@ -893,7 +893,8 @@
893
var this_state_object = this;
894
$.ajax( {
895
url: this.current.url,
896
- crossDomain: true
896
+ crossDomain: true,
897
+ cache: false
898
})
899
.then(function(data) {
900
this_state_object.updateChartWithData(data);
@@ -995,7 +996,8 @@
996
997
$.ajax( {
998
url: this.chart_url,
998
- crossDomain: true
999
+ crossDomain: true,
1000
+ cache: false
1001
})
1002
.done(function(chart) {
1003
chart.url = this_state_object.chart_url;
@@ -1039,7 +1041,7 @@
1041
this.element.innerHTML = '<div class="netdata-message netdata-' + type + '-message" style="font-size: x-small; overflow: hidden; width: 100%; height: 100%;"><small>'
1042
+ msg
1043
+ '</small></div>';
1042
-
1044
+
1045
// reset the creation datetime
1046
// since we overwrote the whole element
1047
this.created_ms = 0
@@ -1270,7 +1272,11 @@
1272
1273
NETDATA.peityInitialize = function(callback) {
1274
if(typeof netdataNoPeitys == 'undefined' || !netdataNoPeitys) {
1273
- $.getScript(NETDATA.peity_js)
1275
+ $.ajax({
1276
+ url: NETDATA.peity_js,
1277
+ cache: true,
1278
+ dataType: "script"
1279
+ })
1280
.done(function() {
1281
NETDATA.registerChartLibrary('peity', NETDATA.peity_js);
1282
})
@@ -1307,7 +1313,11 @@
1313
1314
NETDATA.sparklineInitialize = function(callback) {
1315
if(typeof netdataNoSparklines == 'undefined' || !netdataNoSparklines) {
1310
- $.getScript(NETDATA.sparkline_js)
1316
+ $.ajax({
1317
+ url: NETDATA.sparkline_js,
1318
+ cache: true,
1319
+ dataType: "script"
1320
+ })
1321
.done(function() {
1322
NETDATA.registerChartLibrary('sparkline', NETDATA.sparkline_js);
1323
})
@@ -1568,7 +1578,11 @@
1578
1579
NETDATA.dygraphInitialize = function(callback) {
1580
if(typeof netdataNoDygraphs == 'undefined' || !netdataNoDygraphs) {
1571
- $.getScript(NETDATA.dygraph_js)
1581
+ $.ajax({
1582
+ url: NETDATA.dygraph_js,
1583
+ cache: true,
1584
+ dataType: "script"
1585
+ })
1586
.done(function() {
1587
NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js);
1588
})
@@ -1924,7 +1938,11 @@
1938
else {
1939
NETDATA._loadCSS(NETDATA.morris_css);
1940
1927
- $.getScript(NETDATA.morris_js)
1941
+ $.ajax({
1942
+ url: NETDATA.morris_js,
1943
+ cache: true,
1944
+ dataType: "script"
1945
+ })
1946
.done(function() {
1947
NETDATA.registerChartLibrary('morris', NETDATA.morris_js);
1948
})
@@ -1981,7 +1999,11 @@
1999
2000
NETDATA.raphaelInitialize = function(callback) {
2001
if(typeof netdataStopRaphael == 'undefined') {
1984
- $.getScript(NETDATA.raphael_js)
2002
+ $.ajax({
2003
+ url: NETDATA.raphael_js,
2004
+ cache: true,
2005
+ dataType: "script"
2006
+ })
2007
.done(function() {
2008
NETDATA.registerChartLibrary('raphael', NETDATA.raphael_js);
2009
})
@@ -2019,7 +2041,11 @@
2041
2042
NETDATA.googleInitialize = function(callback) {
2043
if(typeof netdataNoGoogleCharts == 'undefined' || !netdataNoGoogleCharts) {
2022
- $.getScript(NETDATA.google_js)
2044
+ $.ajax({
2045
+ url: NETDATA.google_js,
2046
+ cache: true,
2047
+ dataType: "script"
2048
+ })
2049
.done(function() {
2050
NETDATA.registerChartLibrary('google', NETDATA.google_js);
2051
@@ -2256,7 +2282,12 @@
2282
2283
NETDATA.errorReset();
2284
NETDATA._loadjQuery(function() {
2259
- $.getScript(NETDATA.serverDefault + 'lib/visible.js').then(function() {
2285
+ $.ajax({
2286
+ url: NETDATA.serverDefault + 'lib/visible.js',
2287
+ cache: true,
2288
+ dataType: "script"
2289
+ })
2290
+ .then(function() {
2291
NETDATA._loadCSS(NETDATA.dashboard_css);
2292
2293
if(typeof netdataDontStart == 'undefined' || !netdataDontStart)