]> arthur.barton.de Git - netdata.git/commitdiff
prevent a crash when the ARL is empty; fixes #1700
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Wed, 1 Feb 2017 19:27:13 +0000 (21:27 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Wed, 1 Feb 2017 19:27:13 +0000 (21:27 +0200)
src/adaptive_resortable_list.c
src/proc_net_netstat.c

index a37c396fa89ea63e1446fbe80af5b153451558d3..ac525dc6c14b3fadb418a7a3e9ab442c50821625 100644 (file)
@@ -52,7 +52,6 @@ void arl_free(ARL_BASE *arl_base) {
 }
 
 void arl_begin(ARL_BASE *base) {
-    ARL_ENTRY *e;
 
 #ifdef NETDATA_INTERNAL_CHECKS
     if(likely(base->iteration > 10)) {
@@ -89,7 +88,8 @@ void arl_begin(ARL_BASE *base) {
     if(unlikely(base->added || base->iteration % base->rechecks) == 1) {
         base->added = 0;
         base->wanted = 0;
-        for(e = base->head; e ; e = e->next) {
+        ARL_ENTRY *e = base->head;
+        while(e) {
             if(e->flags & ARL_ENTRY_FLAG_FOUND) {
 
                 // remove the found flag
@@ -98,25 +98,48 @@ void arl_begin(ARL_BASE *base) {
                 // count it in wanted
                 if(e->flags & ARL_ENTRY_FLAG_EXPECTED)
                     base->wanted++;
+
             }
-            else if(e->flags & ARL_ENTRY_FLAG_DYNAMIC) {
+            else if(e->flags & ARL_ENTRY_FLAG_DYNAMIC && !(base->head == e && !e->next)) { // not last entry
                 // we can remove this entry
                 // it is not found, and it was created because
                 // it was found in the source file
+
+                // remember the next one
+                ARL_ENTRY *t = e->next;
+
+                // remove it from the list
                 if(e->next) e->next->prev = e->prev;
                 if(e->prev) e->prev->next = e->next;
                 if(base->head == e) base->head = e->next;
+
+                // free it
                 freez(e->name);
                 freez(e);
 
+                // count it
                 base->fred++;
+
+                // continue
+                e = t;
+                continue;
             }
+
+            e = e->next;
         }
     }
 
+    if(unlikely(!base->head)) {
+        // hm... no nodes at all in the list #1700
+        // add a fake one to prevent a crash
+        // this is better than checking for the existence of nodes all the time
+        arl_expect(base, "a-really-not-existing-source-keyword", NULL);
+    }
+
     base->iteration++;
     base->next_keyword = base->head;
     base->found = 0;
+
 }
 
 // register an expected keyword to the ARL
@@ -153,7 +176,7 @@ int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const char *val
             break;
 
 #ifdef NETDATA_INTERNAL_CHECKS
-    if(unlikely(e == base->next_keyword))
+    if(unlikely(base->next_keyword && e == base->next_keyword))
         fatal("Internal Error: e == base->last");
 #endif
 
index 8741a71c94fb36f9e724edb61cc2faee9e8a716c..37b7add1b8fdb3930534dd59eec75de9b038c9ac 100644 (file)
@@ -206,6 +206,9 @@ int do_proc_net_netstat(int update_every, usec_t dt) {
     size_t lines = procfile_lines(ff), l;
     size_t words;
 
+    arl_begin(arl_ipext);
+    arl_begin(arl_tcpext);
+
     for(l = 0; l < lines ;l++) {
         char *key = procfile_lineword(ff, l, 0);
         uint32_t hash = simple_hash(key);
@@ -219,7 +222,6 @@ int do_proc_net_netstat(int update_every, usec_t dt) {
                 continue;
             }
 
-            arl_begin(arl_ipext);
             parse_line_pair(ff, arl_ipext, h, l);
 
             RRDSET *st;
@@ -371,7 +373,6 @@ int do_proc_net_netstat(int update_every, usec_t dt) {
                 continue;
             }
 
-            arl_begin(arl_tcpext);
             parse_line_pair(ff, arl_tcpext, h, l);
 
             RRDSET *st;