@cryptotaxi247 / netdata-1 / commits / e29c2bd77

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)