@cryptotaxi247 / netdata-1 / commits / a689b9007

will not load dimensions if they are too old; threads are now handled with an array; possible fix for the defunct issue

Costa Tsaousis (ktsaou) committed Mar 12, 2015 at 23:34 UTC a689b90076ffb089db188d0cd469e724e6909d24
1 file changed +359 -245
netdata.c
+359 -245
@@ -37,6 +37,8 @@
37 #include <dirent.h>
38 #include <sys/mman.h>
39
40 +void process_childs(int wait);
41 +
42 // enabling this will detach the plugins from netdata
43 // each plugin will have its own process group
44 // #define DETACH_PLUGINS_FROM_NETDATA
@@ -884,22 +886,22 @@ const char *chart_type_name(int chart_type)
886 // ----------------------------------------------------------------------------
887 // algorithms types
888
887 -#define RRD_DIMENSION_ABSOLUTE_NAME "absolute"
888 -#define RRD_DIMENSION_INCREMENTAL_NAME "incremental"
889 -#define RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL_NAME "percentage-of-incremental-row"
890 -#define RRD_DIMENSION_PCENT_OVER_ROW_TOTAL_NAME "percentage-of-absolute-row"
889 +#define RRD_DIMENSION_ABSOLUTE_NAME "absolute"
890 +#define RRD_DIMENSION_INCREMENTAL_NAME "incremental"
891 +#define RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL_NAME "percentage-of-incremental-row"
892 +#define RRD_DIMENSION_PCENT_OVER_ROW_TOTAL_NAME "percentage-of-absolute-row"
893
892 -#define RRD_DIMENSION_ABSOLUTE 0
893 -#define RRD_DIMENSION_INCREMENTAL 1
894 +#define RRD_DIMENSION_ABSOLUTE 0
895 +#define RRD_DIMENSION_INCREMENTAL 1
896 #define RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL 2
895 -#define RRD_DIMENSION_PCENT_OVER_ROW_TOTAL 3
897 +#define RRD_DIMENSION_PCENT_OVER_ROW_TOTAL 3
898
899 int algorithm_id(const char *name)
900 {
899 - if(strcmp(name, RRD_DIMENSION_ABSOLUTE_NAME) == 0) return RRD_DIMENSION_ABSOLUTE;
900 - if(strcmp(name, RRD_DIMENSION_INCREMENTAL_NAME) == 0) return RRD_DIMENSION_INCREMENTAL;
901 - if(strcmp(name, RRD_DIMENSION_PCENT_OVER_ROW_TOTAL_NAME) == 0) return RRD_DIMENSION_PCENT_OVER_ROW_TOTAL;
902 - if(strcmp(name, RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL_NAME) == 0) return RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL;
901 + if(strcmp(name, RRD_DIMENSION_ABSOLUTE_NAME) == 0) return RRD_DIMENSION_ABSOLUTE;
902 + if(strcmp(name, RRD_DIMENSION_INCREMENTAL_NAME) == 0) return RRD_DIMENSION_INCREMENTAL;
903 + if(strcmp(name, RRD_DIMENSION_PCENT_OVER_ROW_TOTAL_NAME) == 0) return RRD_DIMENSION_PCENT_OVER_ROW_TOTAL;
904 + if(strcmp(name, RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL_NAME) == 0) return RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL;
905 return RRD_DIMENSION_ABSOLUTE;
906 }
907
@@ -1153,80 +1155,82 @@ calculated_number unpack_storage_number(storage_number value)
1155 }
1156
1157
1156 -#define RRD_STATS_MAGIC "NETDATA CACHE STATS FILE V008"
1157 -#define RRD_DIMENSION_MAGIC "NETDATA CACHE DIMENSION FILE V008"
1158 +#define RRD_STATS_MAGIC "NETDATA CACHE STATS FILE V009"
1159 +#define RRD_DIMENSION_MAGIC "NETDATA CACHE DIMENSION FILE V009"
1160
1161 struct rrd_dimension {
1160 - char magic[sizeof(RRD_DIMENSION_MAGIC) + 1];// our magic
1161 - char id[RRD_STATS_NAME_MAX + 1]; // the id of this dimension (for internal identification)
1162 - char *name; // the name of this dimension (as presented to user)
1162 + char magic[sizeof(RRD_DIMENSION_MAGIC) + 1]; // our magic
1163 + char id[RRD_STATS_NAME_MAX + 1]; // the id of this dimension (for internal identification)
1164 + char *name; // the name of this dimension (as presented to user)
1165 char cache_file[FILENAME_MAX+1];
1166
1165 - unsigned long hash; // a simple hash on the id, to speed up searching
1166 - // we first compare hashes, and only if the hashes are equal we do string comparisons
1167 + unsigned long hash; // a simple hash on the id, to speed up searching
1168 + // we first compare hashes, and only if the hashes are equal we do string comparisons
1169 +
1170 + long entries; // how many entries this dimension has
1171 + // this should be the same to the entries of the data set
1172
1168 - long entries; // how many entries this dimension has
1169 - // this should be the same to the entries of the data set
1170 - long current_entry; // the entry that is currently being updated
1173 + long current_entry; // the entry that is currently being updated
1174 + int update_every; // every how many seconds is this updated?
1175
1172 - int hidden; // if set to non zero, this dimension will not be sent to the client
1173 - int mapped; // 1 if the file is mapped
1174 - unsigned long memsize; // the memory allocated for this dimension
1176 + int hidden; // if set to non zero, this dimension will not be sent to the client
1177 + int mapped; // 1 if the file is mapped
1178 + unsigned long memsize; // the memory allocated for this dimension
1179
1180 int algorithm;
1181 long multiplier;
1182 long divisor;
1183
1180 - struct timeval last_collected_time; // when was this dimension last updated
1181 - // this is only used to detect un-updated dimensions
1182 - // which are removed after some time
1184 + struct timeval last_collected_time; // when was this dimension last updated
1185 + // this is only used to detect un-updated dimensions
1186 + // which are removed after some time
1187
1188 calculated_number calculated_value;
1189 calculated_number last_calculated_value;
1190
1187 - collected_number collected_value; // the value collected at this round
1191 + collected_number collected_value; // the value collected at this round
1192 collected_number last_collected_value; // the value that was collected at the last round
1193
1190 - struct rrd_dimension *next; // linking of dimensions within the same data set
1194 + struct rrd_dimension *next; // linking of dimensions within the same data set
1195
1192 - storage_number values[]; // the array of values - THIS HAS TO BE THE LAST MEMBER
1196 + storage_number values[]; // the array of values - THIS HAS TO BE THE LAST MEMBER
1197 };
1198 typedef struct rrd_dimension RRD_DIMENSION;
1199
1200 struct rrd_stats {
1197 - char magic[sizeof(RRD_STATS_MAGIC) + 1];// our magic
1201 + char magic[sizeof(RRD_STATS_MAGIC) + 1]; // our magic
1202
1199 - char id[RRD_STATS_NAME_MAX + 1]; // id of the data set
1200 - char *name; // name of the data set
1201 - char *cache_dir; // the directory to store dimension maps
1203 + char id[RRD_STATS_NAME_MAX + 1]; // id of the data set
1204 + char *name; // name of the data set
1205 + char *cache_dir; // the directory to store dimension maps
1206 char cache_file[FILENAME_MAX+1];
1207
1204 - char *type; // the type of graph RRD_TYPE_* (a category, for determining graphing options)
1205 - char *family; // the family of this data set (for grouping them together)
1206 - char *title; // title shown to user
1207 - char *units; // units of measurement
1208 + char *type; // the type of graph RRD_TYPE_* (a category, for determining graphing options)
1209 + char *family; // the family of this data set (for grouping them together)
1210 + char *title; // title shown to user
1211 + char *units; // units of measurement
1212
1213 pthread_rwlock_t rwlock;
1210 - unsigned long counter; // the number of times we added values to this rrd
1211 - unsigned long counter_done; // the number of times we added values to this rrd
1214 + unsigned long counter; // the number of times we added values to this rrd
1215 + unsigned long counter_done; // the number of times we added values to this rrd
1216
1213 - int mapped; // if set to 1, this is memory mapped
1214 - unsigned long memsize; // how much mem we have allocated for this (without dimensions)
1217 + int mapped; // if set to 1, this is memory mapped
1218 + unsigned long memsize; // how much mem we have allocated for this (without dimensions)
1219
1216 - unsigned long hash_name; // a simple hash on the name
1217 - unsigned long hash; // a simple hash on the id, to speed up searching
1218 - // we first compare hashes, and only if the hashes are equal we do string comparisons
1220 + unsigned long hash_name; // a simple hash on the name
1221 + unsigned long hash; // a simple hash on the id, to speed up searching
1222 + // we first compare hashes, and only if the hashes are equal we do string comparisons
1223
1224 long priority;
1225
1222 - long entries; // total number of entries in the data set
1223 - long current_entry; // the entry that is currently being updated
1224 - // it goes around in a round-robin fashion
1226 + long entries; // total number of entries in the data set
1227 + long current_entry; // the entry that is currently being updated
1228 + // it goes around in a round-robin fashion
1229
1226 - int update_every; // every how many seconds is this updated?
1227 - unsigned long long first_entry_t; // the timestamp (in microseconds) of the oldest entry in the db
1228 - struct timeval last_updated; // when this data set was last updated (updated every time the rrd_stats_done() function)
1229 - struct timeval last_collected_time; //
1230 + int update_every; // every how many seconds is this updated?
1231 + unsigned long long first_entry_t; // the timestamp (in microseconds) of the oldest entry in the db
1232 + struct timeval last_updated; // when this data set was last updated (updated every time the rrd_stats_done() function)
1233 + struct timeval last_collected_time; //
1234 unsigned long long usec_since_last_update;
1235
1236 total_number collected_total;
@@ -1235,12 +1239,12 @@ struct rrd_stats {
1239 int chart_type;
1240 int debug;
1241 int enabled;
1238 - int isdetail; // if set, the data set should be considered as a detail of another
1239 - // (the master data set should be the one that has the same family and is not detail)
1242 + int isdetail; // if set, the data set should be considered as a detail of another
1243 + // (the master data set should be the one that has the same family and is not detail)
1244
1241 - RRD_DIMENSION *dimensions; // the actual data for every dimension
1245 + RRD_DIMENSION *dimensions; // the actual data for every dimension
1246
1243 - struct rrd_stats *next; // linking of rrd stats
1247 + struct rrd_stats *next; // linking of rrd stats
1248 };
1249 typedef struct rrd_stats RRD_STATS;
1250
@@ -1294,6 +1298,21 @@ char *rrd_stats_cache_dir(const char *id)
1298 return ret;
1299 }
1300
1301 +void rrd_stats_reset(RRD_STATS *st)
1302 +{
1303 + st->last_collected_time.tv_sec = 0;
1304 + st->last_collected_time.tv_usec = 0;
1305 + st->current_entry = 0;
1306 + st->counter_done = 0;
1307 +
1308 + RRD_DIMENSION *rd;
1309 + for(rd = st->dimensions; rd ; rd = rd->next) {
1310 + rd->last_collected_time.tv_sec = 0;
1311 + rd->last_collected_time.tv_usec = 0;
1312 + rd->current_entry = 0;
1313 + }
1314 +}
1315 +
1316 RRD_STATS *rrd_stats_create(const char *type, const char *id, const char *name, const char *family, const char *title, const char *units, long priority, int update_every, int chart_type)
1317 {
1318 if(!id || !id[0]) {
@@ -1425,6 +1444,9 @@ RRD_DIMENSION *rrd_stats_dimension_add(RRD_STATS *st, const char *id, const char
1444 snprintf(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
1445 rd = (RRD_DIMENSION *)mymmap(fullfilename, size);
1446 if(rd) {
1447 + struct timeval now;
1448 + gettimeofday(&now, NULL);
1449 +
1450 if(strcmp(rd->magic, RRD_DIMENSION_MAGIC) != 0) {
1451 errno = 0;
1452 error("File %s does not have our version. Clearing it.", fullfilename);
@@ -1450,6 +1472,16 @@ RRD_DIMENSION *rrd_stats_dimension_add(RRD_STATS *st, const char *id, const char
1472 error("File %s does not have the same algorithm. Clearing it.", fullfilename);
1473 bzero(rd, size);
1474 }
1475 + else if(rd->update_every != st->update_every) {
1476 + errno = 0;
1477 + error("File %s does not have the same refresh frequency. Clearing it.", fullfilename);
1478 + bzero(rd, size);
1479 + }
1480 + else if(usecdiff(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * 1000000ULL)) {
1481 + errno = 0;
1482 + error("File %s is too old. Clearing it.", fullfilename);
1483 + bzero(rd, size);
1484 + }
1485 else if(strcmp(rd->id, id) != 0) {
1486 errno = 0;
1487 error("File %s does not have our dimension id. Unmapping it.", fullfilename);
@@ -1497,6 +1529,7 @@ RRD_DIMENSION *rrd_stats_dimension_add(RRD_STATS *st, const char *id, const char
1529 if(!rd->divisor) rd->divisor = 1;
1530
1531 rd->entries = st->entries;
1532 + rd->update_every = st->update_every;
1533
1534 // append this dimension
1535 if(!st->dimensions)
@@ -3996,6 +4029,14 @@ void *socket_listen_main(void *ptr)
4029 struct timeval tv;
4030 int retval;
4031
4032 + if(ptr) { ; }
4033 +
4034 + if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
4035 + error("Cannot set pthread cancel type to DEFERRED.");
4036 +
4037 + if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
4038 + error("Cannot set pthread cancel state to ENABLE.");
4039 +
4040 // int listener = create_listen_socket(listen_port);
4041 int listener = listen_fd;
4042 if(listener == -1) fatal("LISTENER: Cannot create listening socket on port 19999.");
@@ -4040,7 +4081,9 @@ void *socket_listen_main(void *ptr)
4081 else debug(D_WEB_CLIENT, "LISTENER: select() didn't do anything.");
4082
4083 }
4043 - //else debug(D_WEB_CLIENT, "LISTENER: select() timeout.");
4084 + //else {
4085 + // debug(D_WEB_CLIENT, "LISTENER: select() timeout.");
4086 + //}
4087
4088 // cleanup unused clients
4089 for(w = web_clients; w ; w = w?w->next:NULL) {
@@ -4071,13 +4114,14 @@ void *socket_listen_main(void *ptr)
4114 int do_proc_net_dev() {
4115 static int enable_new_interfaces = -1;
4116 static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_fifo = -1, do_compressed = -1;
4117 + static FILE *fp = NULL;
4118
4119 if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", 1);
4120
4121 if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", 1);
4122 if(do_packets == -1) do_packets = config_get_boolean("plugin:proc:/proc/net/dev", "packets for all interfaces", 1);
4079 - if(do_errors == -1) do_errors = config_get_boolean("plugin:proc:/proc/net/dev", "errors for all interfaces", 1);
4080 - if(do_fifo == -1) do_fifo = config_get_boolean("plugin:proc:/proc/net/dev", "fifo for all interfaces", 1);
4123 + if(do_errors == -1) do_errors = config_get_boolean("plugin:proc:/proc/net/dev", "errors for all interfaces", 1);
4124 + if(do_fifo == -1) do_fifo = config_get_boolean("plugin:proc:/proc/net/dev", "fifo for all interfaces", 1);
4125 if(do_compressed == -1) do_compressed = config_get_boolean("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", 1);
4126
4127 char buffer[MAX_PROC_NET_DEV_LINE+1] = "";
@@ -4088,10 +4132,20 @@ int do_proc_net_dev() {
4132 int r;
4133 char *p;
4134
4091 - FILE *fp = fopen("/proc/net/dev", "r");
4135 + if(fp) {
4136 + if(fseek(fp, 0, SEEK_SET) == -1) {
4137 + error("Re-opening file /proc/net/dev.");
4138 + fclose(fp);
4139 + fp = NULL;
4140 + }
4141 + }
4142 +
4143 if(!fp) {
4093 - error("Cannot read /proc/net/dev.");
4094 - return 1;
4144 + fp = fopen("/proc/net/dev", "r");
4145 + if(!fp) {
4146 + error("Cannot read /proc/net/dev.");
4147 + return 1;
4148 + }
4149 }
4150
4151 // skip the first two lines
@@ -4216,7 +4270,6 @@ int do_proc_net_dev() {
4270 }
4271 }
4272
4219 - fclose(fp);
4273 return 0;
4274 }
4275
@@ -4229,6 +4282,7 @@ int do_proc_net_dev() {
4282 int do_proc_diskstats() {
4283 static int enable_new_disks = -1;
4284 static int do_io = -1, do_ops = -1, do_merged_ops = -1, do_iotime = -1, do_cur_ops = -1;
4285 + static FILE *fp = NULL;
4286
4287 if(enable_new_disks == -1) enable_new_disks = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", 1);
4288
@@ -4244,10 +4298,20 @@ int do_proc_diskstats() {
4298 int r;
4299 char *p;
4300
4247 - FILE *fp = fopen("/proc/diskstats", "r");
4301 + if(fp) {
4302 + if(fseek(fp, 0, SEEK_SET) == -1) {
4303 + error("Re-opening file /proc/diskstats.");
4304 + fclose(fp);
4305 + fp = NULL;
4306 + }
4307 + }
4308 +
4309 if(!fp) {
4249 - error("Cannot read /proc/diskstats.");
4250 - return 1;
4310 + fp = fopen("/proc/diskstats", "r");
4311 + if(!fp) {
4312 + error("Cannot read /proc/diskstats.");
4313 + return 1;
4314 + }
4315 }
4316
4317 for(;1;) {
@@ -4514,7 +4578,6 @@ int do_proc_diskstats() {
4578 }
4579 }
4580
4517 - fclose(fp);
4581 return 0;
4582 }
4583
@@ -4525,6 +4588,7 @@ int do_proc_net_snmp() {
4588 static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
4589 do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1,
4590 do_udp_packets = -1, do_udp_errors = -1;
4591 + static FILE *fp = NULL;
4592
4593 if(do_ip_packets == -1) do_ip_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1);
4594 if(do_ip_fragsout == -1) do_ip_fragsout = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragrments sent", 1);
@@ -4539,10 +4603,20 @@ int do_proc_net_snmp() {
4603
4604 char buffer[MAX_PROC_NET_SNMP_LINE+1] = "";
4605
4542 - FILE *fp = fopen("/proc/net/snmp", "r");
4606 + if(fp) {
4607 + if(fseek(fp, 0, SEEK_SET) == -1) {
4608 + error("Re-opening file /proc/net/snmp.");
4609 + fclose(fp);
4610 + fp = NULL;
4611 + }
4612 + }
4613 +
4614 if(!fp) {
4544 - error("Cannot read /proc/net/snmp.");
4545 - return 1;
4615 + fp = fopen("/proc/net/snmp", "r");
4616 + if(!fp) {
4617 + error("Cannot read /proc/net/snmp.");
4618 + return 1;
4619 + }
4620 }
4621
4622 RRD_STATS *st;
@@ -4813,7 +4887,6 @@ int do_proc_net_snmp() {
4887 }
4888 }
4889
4816 - fclose(fp);
4890 return 0;
4891 }
4892
@@ -4822,6 +4895,7 @@ int do_proc_net_snmp() {
4895
4896 int do_proc_net_netstat() {
4897 static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1;
4898 + static FILE *fp = NULL;
4899
4900 if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/netstat", "bandwidth", 1);
4901 if(do_inerrors == -1) do_inerrors = config_get_boolean("plugin:proc:/proc/net/netstat", "input errors", 1);
@@ -4832,10 +4906,20 @@ int do_proc_net_netstat() {
4906
4907 char buffer[MAX_PROC_NET_SNMP_LINE+1] = "";
4908
4835 - FILE *fp = fopen("/proc/net/netstat", "r");
4909 + if(fp) {
4910 + if(fseek(fp, 0, SEEK_SET) == -1) {
4911 + error("Re-opening file /proc/net/netstat.");
4912 + fclose(fp);
4913 + fp = NULL;
4914 + }
4915 + }
4916 +
4917 if(!fp) {
4837 - error("Cannot read /proc/net/netstat.");
4838 - return 1;
4918 + fp = fopen("/proc/net/netstat", "r");
4919 + if(!fp) {
4920 + error("Cannot read /proc/net/netstat.");
4921 + return 1;
4922 + }
4923 }
4924
4925 for(;1;) {
@@ -4978,7 +5062,6 @@ int do_proc_net_netstat() {
5062 }
5063 }
5064
4981 - fclose(fp);
5065 return 0;
5066 }
5067
@@ -4987,6 +5070,7 @@ int do_proc_net_netstat() {
5070
5071 int do_proc_net_stat_conntrack() {
5072 static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1;
5073 + static FILE *fp = NULL;
5074
5075 if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", 1);
5076 if(do_new == -1) do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", 1);
@@ -4998,10 +5082,20 @@ int do_proc_net_stat_conntrack() {
5082
5083 char buffer[MAX_PROC_NET_STAT_CONNTRACK_LINE+1] = "";
5084
5001 - FILE *fp = fopen("/proc/net/stat/nf_conntrack", "r");
5085 + if(fp) {
5086 + if(fseek(fp, 0, SEEK_SET) == -1) {
5087 + error("Re-opening file /proc/net/stat/nf_conntrack.");
5088 + fclose(fp);
5089 + fp = NULL;
5090 + }
5091 + }
5092 +
5093 if(!fp) {
5003 - error("Cannot read /proc/net/stat/nf_conntrack.");
5004 - return 1;
5094 + fp = fopen("/proc/net/stat/nf_conntrack", "r");
5095 + if(!fp) {
5096 + error("Cannot read /proc/net/stat/nf_conntrack.");
5097 + return 1;
5098 + }
5099 }
5100
5101 // read and discard the header
@@ -5025,24 +5119,23 @@ int do_proc_net_stat_conntrack() {
5119 if(!aentries) aentries = tentries;
5120
5121 // sum all the cpus together
5028 - asearched += tsearched; // conntrack.search
5029 - afound += tfound; // conntrack.search
5030 - anew += tnew; // conntrack.new
5031 - ainvalid += tinvalid; // conntrack.new
5032 - aignore += tignore; // conntrack.new
5033 - adelete += tdelete; // conntrack.changes
5034 - adelete_list += tdelete_list; // conntrack.changes
5035 - ainsert += tinsert; // conntrack.changes
5036 - ainsert_failed += tinsert_failed; // conntrack.errors
5037 - adrop += tdrop; // conntrack.errors
5038 - aearly_drop += tearly_drop; // conntrack.errors
5039 - aicmp_error += ticmp_error; // conntrack.errors
5040 - aexpect_new += texpect_new; // conntrack.expect
5041 - aexpect_create += texpect_create; // conntrack.expect
5042 - aexpect_delete += texpect_delete; // conntrack.expect
5043 - asearch_restart += tsearch_restart; // conntrack.search
5122 + asearched += tsearched; // conntrack.search
5123 + afound += tfound; // conntrack.search
5124 + anew += tnew; // conntrack.new
5125 + ainvalid += tinvalid; // conntrack.new
5126 + aignore += tignore; // conntrack.new
5127 + adelete += tdelete; // conntrack.changes
5128 + adelete_list += tdelete_list; // conntrack.changes
5129 + ainsert += tinsert; // conntrack.changes
5130 + ainsert_failed += tinsert_failed; // conntrack.errors
5131 + adrop += tdrop; // conntrack.errors
5132 + aearly_drop += tearly_drop; // conntrack.errors
5133 + aicmp_error += ticmp_error; // conntrack.errors
5134 + aexpect_new += texpect_new; // conntrack.expect
5135 + aexpect_create += texpect_create; // conntrack.expect
5136 + aexpect_delete += texpect_delete; // conntrack.expect
5137 + asearch_restart += tsearch_restart; // conntrack.search
5138 }
5045 - fclose(fp);
5139
5140 RRD_STATS *st;
5141
@@ -5170,6 +5263,7 @@ int do_proc_net_stat_conntrack() {
5263
5264 int do_proc_net_ip_vs_stats() {
5265 static int do_bandwidth = -1, do_sockets = -1, do_packets = -1;
5266 + static FILE *fp = NULL;
5267
5268 if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS bandwidth", 1);
5269 if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS connections", 1);
@@ -5177,10 +5271,20 @@ int do_proc_net_ip_vs_stats() {
5271
5272 char buffer[MAX_PROC_NET_IPVS_LINE+1] = "";
5273
5180 - FILE *fp = fopen("/proc/net/ip_vs_stats", "r");
5274 + if(fp) {
5275 + if(fseek(fp, 0, SEEK_SET) == -1) {
5276 + error("Re-opening file /proc/net/ip_vs_stats.");
5277 + fclose(fp);
5278 + fp = NULL;
5279 + }
5280 + }
5281 +
5282 if(!fp) {
5182 - error("Cannot read /proc/net/ip_vs_stats.");
5183 - return 1;
5283 + fp = fopen("/proc/net/ip_vs_stats", "r");
5284 + if(!fp) {
5285 + error("Cannot read /proc/net/ip_vs_stats.");
5286 + return 1;
5287 + }
5288 }
5289
5290 // read the discard the 2 header lines
@@ -5212,8 +5316,6 @@ int do_proc_net_ip_vs_stats() {
5316 }
5317 if(r != 5) error("Cannot read /proc/net/ip_vs_stats. Expected 5 params, read %d.", r);
5318
5215 - fclose(fp);
5216 -
5319 RRD_STATS *st;
5320
5321 // --------------------------------------------------------------------
@@ -5270,20 +5372,31 @@ int do_proc_net_ip_vs_stats() {
5372
5373 int do_proc_stat() {
5374 static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1;
5375 + static FILE *fp = NULL;
5376
5274 - if(do_cpu == -1) do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", 1);
5377 + if(do_cpu == -1) do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", 1);
5378 if(do_cpu_cores == -1) do_cpu_cores = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", 1);
5379 if(do_interrupts == -1) do_interrupts = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", 1);
5380 if(do_context == -1) do_context = config_get_boolean("plugin:proc:/proc/stat", "context switches", 1);
5278 - if(do_forks == -1) do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", 1);
5381 + if(do_forks == -1) do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", 1);
5382 if(do_processes == -1) do_processes = config_get_boolean("plugin:proc:/proc/stat", "processes running", 1);
5383
5384 char buffer[MAX_PROC_STAT_LINE+1] = "";
5385
5283 - FILE *fp = fopen("/proc/stat", "r");
5386 + if(fp) {
5387 + if(fseek(fp, 0, SEEK_SET) == -1) {
5388 + error("Re-opening file /proc/stat.");
5389 + fclose(fp);
5390 + fp = NULL;
5391 + }
5392 + }
5393 +
5394 if(!fp) {
5285 - error("Cannot read /proc/stat.");
5286 - return 1;
5395 + fp = fopen("/proc/stat", "r");
5396 + if(!fp) {
5397 + error("Cannot read /proc/stat.");
5398 + return 1;
5399 + }
5400 }
5401
5402 unsigned long long processes = 0, running = 0 , blocked = 0;
@@ -5433,7 +5546,6 @@ int do_proc_stat() {
5546 blocked = value;
5547 }
5548 }
5436 - fclose(fp);
5549
5550 // --------------------------------------------------------------------
5551
@@ -5479,6 +5591,7 @@ int do_proc_stat() {
5591
5592 int do_proc_meminfo() {
5593 static int do_ram = -1, do_swap = -1, do_hwcorrupt = -1, do_committed = -1, do_writeback = -1, do_kernel = -1, do_slab = -1;
5594 + static FILE *fp = NULL;
5595
5596 if(do_ram == -1) do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1);
5597 if(do_swap == -1) do_swap = config_get_boolean("plugin:proc:/proc/meminfo", "system swap", 1);
@@ -5490,10 +5603,20 @@ int do_proc_meminfo() {
5603
5604 char buffer[MAX_PROC_MEMINFO_LINE+1] = "";
5605
5493 - FILE *fp = fopen("/proc/meminfo", "r");
5606 + if(fp) {
5607 + if(fseek(fp, 0, SEEK_SET) == -1) {
5608 + error("Re-opening file /proc/meminfo.");
5609 + fclose(fp);
5610 + fp = NULL;
5611 + }
5612 + }
5613 +
5614 if(!fp) {
5495 - error("Cannot read /proc/meminfo.");
5496 - return 1;
5615 + fp = fopen("/proc/meminfo", "r");
5616 + if(!fp) {
5617 + error("Cannot read /proc/meminfo.");
5618 + return 1;
5619 + }
5620 }
5621
5622 int hwcorrupted = 0;
@@ -5565,7 +5688,6 @@ int do_proc_meminfo() {
5688 else if(!DirectMap4k && strcmp(name, "DirectMap4k") == 0) DirectMap4k = value;
5689 else if(!DirectMap2M && strcmp(name, "DirectMap2M") == 0) DirectMap2M = value;
5690 }
5568 - fclose(fp);
5691
5692 RRD_STATS *st;
5693
@@ -5720,17 +5842,28 @@ int do_proc_meminfo() {
5842
5843 int do_proc_vmstat() {
5844 static int do_swapio = -1, do_io = -1, do_pgfaults = -1;
5845 + static FILE *fp = NULL;
5846
5724 - if(do_swapio == -1) do_swapio = config_get_boolean("plugin:proc:/proc/vmstat", "swap i/o", 1);
5725 - if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1);
5847 + if(do_swapio == -1) do_swapio = config_get_boolean("plugin:proc:/proc/vmstat", "swap i/o", 1);
5848 + if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1);
5849 if(do_pgfaults == -1) do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1);
5850
5851 char buffer[MAX_PROC_VMSTAT_LINE+1] = "";
5852
5730 - FILE *fp = fopen("/proc/vmstat", "r");
5853 + if(fp) {
5854 + if(fseek(fp, 0, SEEK_SET) == -1) {
5855 + error("Re-opening file /proc/vmstat.");
5856 + fclose(fp);
5857 + fp = NULL;
5858 + }
5859 + }
5860 +
5861 if(!fp) {
5732 - error("Cannot read /proc/vmstat.");
5733 - return 1;
5862 + fp = fopen("/proc/vmstat", "r");
5863 + if(!fp) {
5864 + error("Cannot read /proc/vmstat.");
5865 + return 1;
5866 + }
5867 }
5868
5869 unsigned long long nr_free_pages = 0, nr_inactive_anon = 0, nr_active_anon = 0, nr_inactive_file = 0, nr_active_file = 0, nr_unevictable = 0, nr_mlock = 0,
@@ -5855,7 +5988,6 @@ int do_proc_vmstat() {
5988 else if(!thp_collapse_alloc_failed && strcmp(name, "thp_collapse_alloc_failed") == 0) thp_collapse_alloc_failed = value;
5989 else if(!thp_split && strcmp(name, "thp_split") == 0) thp_split = value;
5990 }
5858 - fclose(fp);
5991
5992 RRD_STATS *st;
5993
@@ -5938,7 +6070,7 @@ void *proc_main(void *ptr)
6070 config_get_boolean("plugin:proc:/proc/net/dev", "interface fireqos_monitor", 0);
6071
6072 // when ZERO, attempt to do it
5941 - int vdo_proc_net_dev = !config_get_boolean("plugin:proc", "/proc/net/dev", 1);
6073 + int vdo_proc_net_dev = !config_get_boolean("plugin:proc", "/proc/net/dev", 1);
6074 int vdo_proc_diskstats = !config_get_boolean("plugin:proc", "/proc/diskstats", 1);
6075 int vdo_proc_net_snmp = !config_get_boolean("plugin:proc", "/proc/net/snmp", 1);
6076 int vdo_proc_net_netstat = !config_get_boolean("plugin:proc", "/proc/net/netstat", 1);
@@ -5958,15 +6090,15 @@ void *proc_main(void *ptr)
6090 for(;1;) {
6091
6092 // BEGIN -- the job to be done
5961 - if(!vdo_proc_net_dev) vdo_proc_net_dev = do_proc_net_dev(usec);
5962 - if(!vdo_proc_diskstats) vdo_proc_diskstats = do_proc_diskstats(usec);
5963 - if(!vdo_proc_net_snmp) vdo_proc_net_snmp = do_proc_net_snmp(usec);
5964 - if(!vdo_proc_net_netstat) vdo_proc_net_netstat = do_proc_net_netstat(usec);
6093 + if(!vdo_proc_net_dev) vdo_proc_net_dev = do_proc_net_dev(usec);
6094 + if(!vdo_proc_diskstats) vdo_proc_diskstats = do_proc_diskstats(usec);
6095 + if(!vdo_proc_net_snmp) vdo_proc_net_snmp = do_proc_net_snmp(usec);
6096 + if(!vdo_proc_net_netstat) vdo_proc_net_netstat = do_proc_net_netstat(usec);
6097 if(!vdo_proc_net_stat_conntrack) vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(usec);
6098 if(!vdo_proc_net_ip_vs_stats) vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(usec);
5967 - if(!vdo_proc_stat) vdo_proc_stat = do_proc_stat(usec);
5968 - if(!vdo_proc_meminfo) vdo_proc_meminfo = do_proc_meminfo(usec);
5969 - if(!vdo_proc_vmstat) vdo_proc_vmstat = do_proc_vmstat(usec);
6099 + if(!vdo_proc_stat) vdo_proc_stat = do_proc_stat(usec);
6100 + if(!vdo_proc_meminfo) vdo_proc_meminfo = do_proc_meminfo(usec);
6101 + if(!vdo_proc_vmstat) vdo_proc_vmstat = do_proc_vmstat(usec);
6102 // END -- the job is done
6103
6104 // find the time to sleep in order to wait exactly update_every seconds
@@ -6944,7 +7076,25 @@ void *pluginsd_main(void *ptr)
7076 // ----------------------------------------------------------------------------
7077 // main and related functions
7078
6947 -pthread_t *p_proc = NULL, *p_tc = NULL, *p_jitter = NULL, *p_pluginsd = NULL, *p_checks = NULL;
7079 +struct netdata_static_thread {
7080 + char *name;
7081 +
7082 + char *config_section;
7083 + char *config_name;
7084 +
7085 + pthread_t *thread;
7086 + void *(*start_routine) (void *);
7087 +};
7088 +
7089 +struct netdata_static_thread static_threads[] = {
7090 + {"tc", "plugins", "tc", NULL, tc_main},
7091 + {"idlejitter", "plugins", "idlejitter", NULL, cpuidlejitter_main},
7092 + {"proc", "plugins", "proc", NULL, proc_main},
7093 + {"plugins.d", NULL, NULL, NULL, pluginsd_main},
7094 + {"check", "plugins", "checks", NULL, checks_main},
7095 + {"web", NULL, NULL, NULL, socket_listen_main},
7096 + {NULL, NULL, NULL, NULL, NULL}
7097 +};
7098
7099 void kill_childs()
7100 {
@@ -6956,69 +7106,86 @@ void kill_childs()
7106 pthread_cancel(w->thread);
7107 pthread_join(w->thread, NULL);
7108 }
6959 -
6960 - if(p_proc) {
6961 - debug(D_EXIT, "Stopping proc thread");
6962 - pthread_cancel(*p_proc);
6963 - pthread_join(*p_proc, NULL);
6964 - p_proc = NULL;
6965 - }
7109
6967 - if(p_jitter) {
6968 - debug(D_EXIT, "Stopping idlejitter thread");
6969 - pthread_cancel(*p_jitter);
6970 - pthread_join(*p_jitter, NULL);
6971 - p_jitter = NULL;
7110 + int i;
7111 + for (i = 0; static_threads[i].name != NULL ; i++) {
7112 + if(static_threads[i].thread) {
7113 + debug(D_EXIT, "Stopping %s thread", static_threads[i].name);
7114 + pthread_cancel(*static_threads[i].thread);
7115 + pthread_join(*static_threads[i].thread, NULL);
7116 + static_threads[i].thread = NULL;
7117 + }
7118 }
7119
6974 - if(p_checks) {
6975 - debug(D_EXIT, "Stopping self-checks thread");
6976 - pthread_cancel(*p_checks);
6977 - pthread_join(*p_checks, NULL);
6978 - p_checks = NULL;
7120 + if(tc_child_pid) {
7121 + debug(D_EXIT, "Killing tc-qos-helper procees");
7122 + kill(tc_child_pid, SIGTERM);
7123 + waitid(tc_child_pid, 0, &info, WEXITED);
7124 }
7125 + tc_child_pid = 0;
7126
6981 - if(p_tc) {
6982 - if(tc_child_pid) {
6983 - debug(D_EXIT, "Killing tc-qos-helper procees");
6984 - kill(tc_child_pid, SIGTERM);
6985 - waitid(tc_child_pid, 0, &info, WEXITED);
6986 - }
6987 - tc_child_pid = 0;
7127 + struct plugind *cd;
7128 + for(cd = pluginsd_root ; cd ; cd = cd->next) {
7129 + debug(D_EXIT, "Stopping %s plugin thread", cd->id);
7130 + pthread_cancel(cd->thread);
7131 + pthread_join(cd->thread, NULL);
7132
6989 - debug(D_EXIT, "Stopping tc plugin thread");
6990 - pthread_cancel(*p_tc);
6991 - pthread_join(*p_tc, NULL);
6992 - p_tc = NULL;
7133 + if(cd->pid && !cd->obsolete) {
7134 + debug(D_EXIT, "killing %s plugin process", cd->id);
7135 + kill(cd->pid, SIGTERM);
7136 + waitid(cd->pid, 0, &info, WEXITED);
7137 + }
7138 }
7139
6995 - if(p_pluginsd) {
6996 - struct plugind *cd;
6997 - for(cd = pluginsd_root ; cd ; cd = cd->next) {
6998 - debug(D_EXIT, "Stopping %s plugin thread", cd->id);
6999 - pthread_cancel(cd->thread);
7000 - pthread_join(cd->thread, NULL);
7140 + debug(D_EXIT, "All threads/childs stopped.");
7141 +}
7142
7002 - if(cd->pid && !cd->obsolete) {
7003 - debug(D_EXIT, "killing %s plugin process", cd->id);
7004 - kill(cd->pid, SIGTERM);
7005 - waitid(cd->pid, 0, &info, WEXITED);
7006 - }
7143 +void process_childs(int wait)
7144 +{
7145 + siginfo_t info;
7146 + int options = WEXITED;
7147 + if(!wait) options |= WNOHANG;
7148 +
7149 + info.si_pid = 0;
7150 + while(waitid(P_ALL, 0, &info, options) == 0) {
7151 + if(!info.si_pid) break;
7152 + switch(info.si_code) {
7153 + case CLD_EXITED:
7154 + error("pid %d exited with code %d.", info.si_pid, info.si_status);
7155 + break;
7156 +
7157 + case CLD_KILLED:
7158 + error("pid %d killed by signal %d.", info.si_pid, info.si_status);
7159 + break;
7160 +
7161 + case CLD_DUMPED:
7162 + error("pid %d core dumped by signal %d.", info.si_pid, info.si_status);
7163 + break;
7164 +
7165 + case CLD_STOPPED:
7166 + error("pid %d stopped by signal %d.", info.si_pid, info.si_status);
7167 + break;
7168 +
7169 + case CLD_TRAPPED:
7170 + error("pid %d trapped by signal %d.", info.si_pid, info.si_status);
7171 + break;
7172 +
7173 + case CLD_CONTINUED:
7174 + error("pid %d continued by signal %d.", info.si_pid, info.si_status);
7175 + break;
7176 +
7177 + default:
7178 + error("pid %d gave us a SIGCHLD with code %d and status %d.", info.si_pid, info.si_code, info.si_status);
7179 + break;
7180 }
7181
7009 - debug(D_EXIT, "Stopping plugin manager thread");
7010 - pthread_cancel(*p_pluginsd);
7011 - pthread_join(*p_pluginsd, NULL);
7012 - p_pluginsd = NULL;
7182 + // prevent an infinite loop
7183 + info.si_pid = 0;
7184 }
7014 -
7015 - debug(D_EXIT, "All threads/childs stopped.");
7185 }
7186
7187 void sig_handler(int signo)
7188 {
7020 - siginfo_t info;
7021 -
7189 switch(signo) {
7190 case SIGTERM:
7191 case SIGQUIT:
@@ -7034,9 +7201,8 @@ void sig_handler(int signo)
7201 signal(SIGHUP, SIG_IGN);
7202 signal(SIGINT, SIG_IGN);
7203 kill_childs();
7204 + process_childs(0);
7205 rrd_stats_free_all();
7038 - debug(D_EXIT, "Waiting for any child exits...");
7039 - while(waitid(P_ALL, 0, &info, WEXITED|WNOHANG) == 0) if(!info.si_pid) break;
7206 //unlink("/var/run/netdata.pid");
7207 info("NetData exiting. Bye bye...");
7208 exit(1);
@@ -7049,38 +7215,7 @@ void sig_handler(int signo)
7215
7216 case SIGCHLD:
7217 info("Received SIGCHLD (signal %d).", signo);
7052 - while(waitid(P_ALL, 0, &info, WEXITED|WNOHANG) == 0) {
7053 - if(!info.si_pid) break;
7054 - switch(info.si_code) {
7055 - case CLD_EXITED:
7056 - error("pid %d exited with code %d.", info.si_pid, info.si_status);
7057 - break;
7058 -
7059 - case CLD_KILLED:
7060 - error("pid %d killed by signal %d.", info.si_pid, info.si_status);
7061 - break;
7062 -
7063 - case CLD_DUMPED:
7064 - error("pid %d core dumped by signal %d.", info.si_pid, info.si_status);
7065 - break;
7066 -
7067 - case CLD_STOPPED:
7068 - error("pid %d stopped by signal %d.", info.si_pid, info.si_status);
7069 - break;
7070 -
7071 - case CLD_TRAPPED:
7072 - error("pid %d trapped by signal %d.", info.si_pid, info.si_status);
7073 - break;
7074 -
7075 - case CLD_CONTINUED:
7076 - error("pid %d continued by signal %d.", info.si_pid, info.si_status);
7077 - break;
7078 -
7079 - default:
7080 - error("pid %d gave us a SIGCHLD with code %d and status %d.", info.si_pid, info.si_code, info.si_status);
7081 - break;
7082 - }
7083 - }
7218 + process_childs(0);
7219 break;
7220
7221 default:
@@ -7305,7 +7440,7 @@ int become_daemon(int close_all_files, const char *input, const char *output, co
7440 if(fd >= 0) {
7441 char b[100];
7442 sprintf(b, "%d\n", getpid());
7308 - write(fd, b, strlen(b));
7443 + i = write(fd, b, strlen(b));
7444 close(fd);
7445 }
7446 }
@@ -7634,48 +7769,27 @@ int main(int argc, char **argv)
7769 // catch all signals
7770 for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV && i != SIGFPE) signal(i, sig_handler);
7771
7637 - // spawn childs to collect data
7638 - if(config_get_boolean("plugins", "tc", 1)) {
7639 - p_tc = malloc(sizeof(pthread_t));
7640 - if(pthread_create(p_tc, NULL, tc_main, NULL))
7641 - error("failed to create new thread for tc.");
7642 - else if(pthread_detach(*p_tc))
7643 - error("Cannot request detach of newly created tc thread.");
7644 - }
7645 -
7646 - if(config_get_boolean("plugins", "idlejitter", 1)) {
7647 - p_jitter = malloc(sizeof(pthread_t));
7648 - if(pthread_create(p_jitter, NULL, cpuidlejitter_main, NULL))
7649 - error("failed to create new thread for idlejitter.");
7650 - else if(pthread_detach(*p_jitter))
7651 - error("Cannot request detach of newly created idlejitter thread.");
7652 - }
7653 -
7654 - if(config_get_boolean("plugins", "proc", 1)) {
7655 - p_proc = malloc(sizeof(pthread_t));
7656 - if(pthread_create(p_proc, NULL, proc_main, NULL))
7657 - error("failed to create new thread for proc.");
7658 - else if(pthread_detach(*p_proc))
7659 - error("Cannot request detach of newly created proc thread.");
7660 - }
7661 -
7662 - p_pluginsd = malloc(sizeof(pthread_t));
7663 - if(pthread_create(p_pluginsd, NULL, pluginsd_main, NULL))
7664 - error("failed to create new thread for plugins.d.");
7665 - else if(pthread_detach(*p_pluginsd))
7666 - error("Cannot request detach of newly created plugins.d thread.");
7667 -
7668 - if(config_get_boolean("plugins", "checks", (debug_flags & D_CHECKS)?1:0)) {
7669 - p_checks = malloc(sizeof(pthread_t));
7670 - if(pthread_create(p_checks, NULL, checks_main, NULL))
7671 - error("failed to create new thread for checks.");
7672 - else if(pthread_detach(*p_checks))
7673 - error("Cannot request detach of newly created checks thread.");
7772 + for (i = 0; static_threads[i].name != NULL ; i++) {
7773 + struct netdata_static_thread *st = &static_threads[i];
7774 + int doit = 1;
7775 +
7776 + if(st->config_name) doit = config_get_boolean(st->config_section, st->config_name, doit);
7777 +
7778 + if(doit) {
7779 + st->thread = malloc(sizeof(pthread_t));
7780 +
7781 + if(pthread_create(st->thread, NULL, st->start_routine, NULL))
7782 + error("failed to create new thread for %s.", st->name);
7783 +
7784 + else if(pthread_detach(*st->thread))
7785 + error("Cannot request detach of newly created %s thread.", st->name);
7786 + }
7787 }
7788
7789 // the main process - the web server listener
7790 // this never ends
7678 - socket_listen_main(NULL);
7791 + // socket_listen_main(NULL);
7792 + while(1) process_childs(1);
7793
7794 exit(0);
7795 }