Browse Source

allow debugging memory per module (#4524)

* debug info

* removed debug code
Costa Tsaousis 6 years ago
parent
commit
f739ab110b

+ 13 - 0
collectors/proc.plugin/plugin_proc.c

@@ -94,8 +94,12 @@ void *proc_main(void *ptr) {
     usec_t step = localhost->rrd_update_every * USEC_PER_SEC;
     heartbeat_t hb;
     heartbeat_init(&hb);
+    size_t iterations = 0;
 
     while(!netdata_exit) {
+        iterations++;
+        (void)iterations;
+
         usec_t hb_dt = heartbeat_next(&hb, step);
         usec_t duration = 0ULL;
 
@@ -109,10 +113,19 @@ void *proc_main(void *ptr) {
 
             debug(D_PROCNETDEV_LOOP, "PROC calling %s.", pm->name);
 
+//#ifdef NETDATA_LOG_ALLOCATIONS
+//            if(pm->func == do_proc_interrupts)
+//                log_thread_memory_allocations = iterations;
+//#endif
             pm->enabled = !pm->func(localhost->rrd_update_every, hb_dt);
             pm->duration = heartbeat_monotonic_dt_to_now_usec(&hb) - duration;
             duration += pm->duration;
 
+//#ifdef NETDATA_LOG_ALLOCATIONS
+//            if(pm->func == do_proc_interrupts)
+//                log_thread_memory_allocations = 0;
+//#endif
+
             if(unlikely(netdata_exit)) break;
         }
 

+ 1 - 1
database/rrdhost.c

@@ -231,7 +231,7 @@ RRDHOST *rrdhost_create(const char *hostname,
 
     snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir);
     host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename));
-    host->health_default_recipient = strdup("root");
+    host->health_default_recipient = strdupz("root");
 
 
     // ------------------------------------------------------------------------

+ 3 - 3
database/rrdset.c

@@ -616,10 +616,10 @@ RRDSET *rrdset_create_custom(
         st->rrd_memory_mode = (memory_mode == RRD_MEMORY_MODE_NONE) ? RRD_MEMORY_MODE_NONE : RRD_MEMORY_MODE_ALLOC;
     }
 
-    st->plugin_name = plugin?strdup(plugin):NULL;
-    st->module_name = module?strdup(module):NULL;
+    st->plugin_name = plugin?strdupz(plugin):NULL;
+    st->module_name = module?strdupz(module):NULL;
 
-    st->config_section = strdup(config_section);
+    st->config_section = strdupz(config_section);
     st->rrdhost = host;
     st->memsize = size;
     st->entries = entries;

+ 1 - 1
database/rrdsetvar.c

@@ -169,7 +169,7 @@ RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name)
     rs = rrdsetvar_create(st, n, RRDVAR_TYPE_CALCULATED, v, RRDVAR_OPTION_ALLOCATED|RRDVAR_OPTION_CUSTOM_CHART_VAR);
     rrdset_unlock(st);
 
-    free(n);
+    freez(n);
     return rs;
 }
 

+ 1 - 2
libnetdata/buffer/buffer.c

@@ -381,8 +381,7 @@ void buffer_free(BUFFER *b) {
     freez(b);
 }
 
-void buffer_increase(BUFFER *b, size_t free_size_required)
-{
+void buffer_increase(BUFFER *b, size_t free_size_required) {
     buffer_overflow_check(b);
 
     size_t left = b->size - b->len;

+ 46 - 0
libnetdata/clocks/clocks.c

@@ -156,3 +156,49 @@ inline usec_t heartbeat_monotonic_dt_to_now_usec(heartbeat_t *hb) {
     if(!hb || !hb->monotonic) return 0ULL;
     return now_monotonic_usec() - hb->monotonic;
 }
+
+int sleep_usec(usec_t usec) {
+
+#ifndef NETDATA_WITH_USLEEP
+    // we expect microseconds (1.000.000 per second)
+    // but timespec is nanoseconds (1.000.000.000 per second)
+    struct timespec rem, req = {
+            .tv_sec = (time_t) (usec / 1000000),
+            .tv_nsec = (suseconds_t) ((usec % 1000000) * 1000)
+    };
+
+    while (nanosleep(&req, &rem) == -1) {
+        if (likely(errno == EINTR)) {
+            debug(D_SYSTEM, "nanosleep() interrupted (while sleeping for %llu microseconds).", usec);
+            req.tv_sec = rem.tv_sec;
+            req.tv_nsec = rem.tv_nsec;
+        } else {
+            error("Cannot nanosleep() for %llu microseconds.", usec);
+            break;
+        }
+    }
+
+    return 0;
+#else
+    int ret = usleep(usec);
+    if(unlikely(ret == -1 && errno == EINVAL)) {
+        // on certain systems, usec has to be up to 999999
+        if(usec > 999999) {
+            int counter = usec / 999999;
+            while(counter--)
+                usleep(999999);
+
+            usleep(usec % 999999);
+        }
+        else {
+            error("Cannot usleep() for %llu microseconds.", usec);
+            return ret;
+        }
+    }
+
+    if(ret != 0)
+        error("usleep() failed for %llu microseconds.", usec);
+
+    return ret;
+#endif
+}

+ 2 - 0
libnetdata/clocks/clocks.h

@@ -128,4 +128,6 @@ extern usec_t heartbeat_next(heartbeat_t *hb, usec_t tick);
 /* Returns elapsed time in microseconds since last heartbeat */
 extern usec_t heartbeat_monotonic_dt_to_now_usec(heartbeat_t *hb);
 
+extern int sleep_usec(usec_t usec);
+
 #endif /* NETDATA_CLOCKS_H */

+ 119 - 175
libnetdata/libnetdata.c

@@ -27,182 +27,172 @@ const char *program_version = VERSION;
 // routines.
 
 #ifdef NETDATA_LOG_ALLOCATIONS
-static struct memory_statistics {
-    volatile size_t malloc_calls_made;
-    volatile size_t calloc_calls_made;
-    volatile size_t realloc_calls_made;
-    volatile size_t strdup_calls_made;
-    volatile size_t free_calls_made;
-    volatile size_t memory_calls_made;
-    volatile size_t allocated_memory;
-    volatile size_t mmapped_memory;
-} memory_statistics;
-
-static inline void print_allocations(const char *file, const char *function, const unsigned long line) {
-    static struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
-    //if(unlikely(!(memory_statistics.memory_calls_made % 5))) {
-        fprintf(stderr, "(%04lu@%-10.10s:%-15.15s): Allocated %zu KB (+%zu B), mmapped %zu KB (+%zu B): malloc %zu (+%zu), calloc %zu (+%zu), realloc %zu (+%zu), strdup %zu (+%zu), free %zu (+%zu)\n",
-                line, file, function,
-                (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory,
-                (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory,
-                memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made,
-                memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made,
-                memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made,
-                memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made,
-                memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made
-        );
-
-        memcpy(&old, &memory_statistics, sizeof(struct memory_statistics));
-    //}
+static __thread struct memory_statistics {
+    volatile ssize_t malloc_calls_made;
+    volatile ssize_t calloc_calls_made;
+    volatile ssize_t realloc_calls_made;
+    volatile ssize_t strdup_calls_made;
+    volatile ssize_t free_calls_made;
+    volatile ssize_t memory_calls_made;
+    volatile ssize_t allocated_memory;
+    volatile ssize_t mmapped_memory;
+} memory_statistics = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+__thread size_t log_thread_memory_allocations = 0;
+
+static inline void print_allocations(const char *file, const char *function, const unsigned long line, const char *type, size_t size) {
+    static __thread struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+    fprintf(stderr, "%s iteration %zu MEMORY TRACE: %lu@%s : %s : %s : %zu\n",
+            netdata_thread_tag(),
+            log_thread_memory_allocations,
+            line, file, function,
+            type, size
+    );
+
+    fprintf(stderr, "%s iteration %zu MEMORY ALLOCATIONS: (%04lu@%-40.40s:%-40.40s): Allocated %zd KB (%+zd B), mmapped %zd KB (%+zd B): %s : malloc %zd (%+zd), calloc %zd (%+zd), realloc %zd (%+zd), strdup %zd (%+zd), free %zd (%+zd)\n",
+            netdata_thread_tag(),
+            log_thread_memory_allocations,
+            line, file, function,
+            (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory,
+            (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory,
+            type,
+            memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made,
+            memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made,
+            memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made,
+            memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made,
+            memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made
+    );
+
+    memcpy(&old, &memory_statistics, sizeof(struct memory_statistics));
 }
 
-static inline void malloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
-    __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
-#else
-    // this is for debugging - we don't care locking it
-    memory_statistics.memory_calls_made++;
-    memory_statistics.malloc_calls_made++;
-    memory_statistics.allocated_memory += size;
-#endif
-    print_allocations(file, function, line);
+static inline void mmap_accounting(size_t size) {
+    if(log_thread_memory_allocations) {
+        memory_statistics.memory_calls_made++;
+        memory_statistics.mmapped_memory += size;
+    }
 }
 
-static inline void mmap_accounting(size_t size) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
-    __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.mmapped_memory, size, __ATOMIC_SEQ_CST);
-#else
-    // this is for debugging - we don't care locking it
-    memory_statistics.memory_calls_made++;
-    memory_statistics.mmapped_memory += size;
-#endif
+void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) {
+    if(log_thread_memory_allocations) {
+        memory_statistics.memory_calls_made++;
+        memory_statistics.malloc_calls_made++;
+        memory_statistics.allocated_memory += size;
+        print_allocations(file, function, line, "malloc()", size);
+    }
+
+    size_t *n = (size_t *)malloc(sizeof(size_t) + size);
+    if (unlikely(!n)) fatal("mallocz() cannot allocate %zu bytes of memory.", size);
+    *n = size;
+    return (void *)&n[1];
 }
 
-static inline void calloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
-    __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.calloc_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
-#else
-    // this is for debugging - we don't care locking it
-    memory_statistics.memory_calls_made++;
-    memory_statistics.calloc_calls_made++;
-    memory_statistics.allocated_memory += size;
-#endif
-    print_allocations(file, function, line);
+void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) {
+    size = nmemb * size;
+
+    if(log_thread_memory_allocations) {
+        memory_statistics.memory_calls_made++;
+        memory_statistics.calloc_calls_made++;
+        memory_statistics.allocated_memory += size;
+        print_allocations(file, function, line, "calloc()", size);
+    }
+
+    size_t *n = (size_t *)calloc(1, sizeof(size_t) + size);
+    if (unlikely(!n)) fatal("callocz() cannot allocate %zu bytes of memory.", size);
+    *n = size;
+    return (void *)&n[1];
 }
 
-static inline void realloc_accounting(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
-    (void)ptr;
+void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
+    if(!ptr) return mallocz_int(file, function, line, size);
 
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
-    __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.realloc_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
-#else
-    // this is for debugging - we don't care locking it
-    memory_statistics.memory_calls_made++;
-    memory_statistics.realloc_calls_made++;
-    memory_statistics.allocated_memory += size;
-#endif
-    print_allocations(file, function, line);
+    size_t *n = (size_t *)ptr;
+    n--;
+    size_t old_size = *n;
+
+    n = realloc(n, sizeof(size_t) + size);
+    if (unlikely(!n)) fatal("reallocz() cannot allocate %zu bytes of memory (from %zu bytes).", size, old_size);
+
+    if(log_thread_memory_allocations) {
+        memory_statistics.memory_calls_made++;
+        memory_statistics.realloc_calls_made++;
+        memory_statistics.allocated_memory += (size - old_size);
+        print_allocations(file, function, line, "realloc()", size - old_size);
+    }
+
+    *n = size;
+    return (void *)&n[1];
 }
 
-static inline void strdup_accounting(const char *file, const char *function, const unsigned long line, const char *s) {
+char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) {
     size_t size = strlen(s) + 1;
 
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
-    __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.strdup_calls_made, 1, __ATOMIC_SEQ_CST);
-    __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
-#else
-    // this is for debugging - we don't care locking it
-    memory_statistics.memory_calls_made++;
-    memory_statistics.strdup_calls_made++;
-    memory_statistics.allocated_memory += size;
-#endif
-    print_allocations(file, function, line);
+    if(log_thread_memory_allocations) {
+        memory_statistics.memory_calls_made++;
+        memory_statistics.strdup_calls_made++;
+        memory_statistics.allocated_memory += size;
+        print_allocations(file, function, line, "strdup()", size);
+    }
+
+    size_t *n = (size_t *)malloc(sizeof(size_t) + size);
+    if (unlikely(!n)) fatal("strdupz() cannot allocate %zu bytes of memory.", size);
+
+    *n = size;
+    char *t = (char *)&n[1];
+    strcpy(t, s);
+    return t;
 }
 
-static inline void free_accounting(const char *file, const char *function, const unsigned long line, void *ptr) {
-    (void)file;
-    (void)function;
-    (void)line;
+void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) {
+    if(unlikely(!ptr)) return;
 
-    if(likely(ptr)) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
-        __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
-        __atomic_fetch_add(&memory_statistics.free_calls_made, 1, __ATOMIC_SEQ_CST);
-#else
-        // this is for debugging - we don't care locking it
+    size_t *n = (size_t *)ptr;
+    n--;
+    size_t size = *n;
+
+    if(log_thread_memory_allocations) {
         memory_statistics.memory_calls_made++;
         memory_statistics.free_calls_made++;
-#endif
+        memory_statistics.allocated_memory -= size;
+        print_allocations(file, function, line, "free()", size);
     }
-}
-#endif
 
-#ifdef NETDATA_LOG_ALLOCATIONS
-char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) {
-    strdup_accounting(file, function, line, s);
+    free(n);
+}
 #else
-char *strdupz(const char *s) {
-#endif
 
+char *strdupz(const char *s) {
     char *t = strdup(s);
     if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s);
     return t;
 }
 
-#ifdef NETDATA_LOG_ALLOCATIONS
-void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) {
-    malloc_accounting(file, function, line, size);
-#else
-void *mallocz(size_t size) {
-#endif
+void freez(void *ptr) {
+    free(ptr);
+}
 
+void *mallocz(size_t size) {
     void *p = malloc(size);
     if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size);
     return p;
 }
 
-#ifdef NETDATA_LOG_ALLOCATIONS
-void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) {
-    calloc_accounting(file, function, line, nmemb * size);
-#else
 void *callocz(size_t nmemb, size_t size) {
-#endif
-
     void *p = calloc(nmemb, size);
     if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size);
     return p;
 }
 
-#ifdef NETDATA_LOG_ALLOCATIONS
-void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
-    realloc_accounting(file, function, line, ptr, size);
-#else
 void *reallocz(void *ptr, size_t size) {
-#endif
-
     void *p = realloc(ptr, size);
     if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size);
     return p;
 }
 
-#ifdef NETDATA_LOG_ALLOCATIONS
-void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) {
-    free_accounting(file, function, line, ptr);
-#else
-void freez(void *ptr) {
 #endif
 
-    free(ptr);
-}
+// --------------------------------------------------------------------------------------------------------------------
 
 void json_escape_string(char *dst, const char *src, size_t size) {
     const char *t;
@@ -235,52 +225,6 @@ void json_fix_string(char *s) {
     }
 }
 
-int sleep_usec(usec_t usec) {
-
-#ifndef NETDATA_WITH_USLEEP
-    // we expect microseconds (1.000.000 per second)
-    // but timespec is nanoseconds (1.000.000.000 per second)
-    struct timespec rem, req = {
-            .tv_sec = (time_t) (usec / 1000000),
-            .tv_nsec = (suseconds_t) ((usec % 1000000) * 1000)
-    };
-
-    while (nanosleep(&req, &rem) == -1) {
-        if (likely(errno == EINTR)) {
-            debug(D_SYSTEM, "nanosleep() interrupted (while sleeping for %llu microseconds).", usec);
-            req.tv_sec = rem.tv_sec;
-            req.tv_nsec = rem.tv_nsec;
-        } else {
-            error("Cannot nanosleep() for %llu microseconds.", usec);
-            break;
-        }
-    }
-
-    return 0;
-#else
-    int ret = usleep(usec);
-    if(unlikely(ret == -1 && errno == EINVAL)) {
-        // on certain systems, usec has to be up to 999999
-        if(usec > 999999) {
-            int counter = usec / 999999;
-            while(counter--)
-                usleep(999999);
-
-            usleep(usec % 999999);
-        }
-        else {
-            error("Cannot usleep() for %llu microseconds.", usec);
-            return ret;
-        }
-    }
-
-    if(ret != 0)
-        error("usleep() failed for %llu microseconds.", usec);
-
-    return ret;
-#endif
-}
-
 unsigned char netdata_map_chart_names[256] = {
         [0] = '\0', //
         [1] = '_', //

+ 23 - 24
libnetdata/libnetdata.h

@@ -204,26 +204,6 @@
 
 #define GUID_LEN 36
 
-#include "os.h"
-#include "storage_number/storage_number.h"
-#include "buffer/buffer.h"
-#include "locks/locks.h"
-#include "avl/avl.h"
-#include "inlined.h"
-#include "clocks/clocks.h"
-#include "threads/threads.h"
-#include "popen/popen.h"
-#include "simple_pattern/simple_pattern.h"
-#include "socket/socket.h"
-#include "config/appconfig.h"
-#include "log/log.h"
-#include "procfile/procfile.h"
-#include "dictionary/dictionary.h"
-#include "eval/eval.h"
-#include "statistical/statistical.h"
-#include "adaptive_resortable_list/adaptive_resortable_list.h"
-#include "url/url.h"
-
 extern void netdata_fix_chart_id(char *s);
 extern void netdata_fix_chart_name(char *s);
 
@@ -237,6 +217,7 @@ extern int  snprintfz(char *dst, size_t n, const char *fmt, ...) PRINTFLIKE(3, 4
 
 // memory allocation functions that handle failures
 #ifdef NETDATA_LOG_ALLOCATIONS
+extern __thread size_t log_thread_memory_allocations;
 #define strdupz(s) strdupz_int(__FILE__, __FUNCTION__, __LINE__, s)
 #define callocz(nmemb, size) callocz_int(__FILE__, __FUNCTION__, __LINE__, nmemb, size)
 #define mallocz(size) mallocz_int(__FILE__, __FUNCTION__, __LINE__, size)
@@ -248,13 +229,13 @@ extern void *callocz_int(const char *file, const char *function, const unsigned
 extern void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size);
 extern void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size);
 extern void freez_int(const char *file, const char *function, const unsigned long line, void *ptr);
-#else
+#else // NETDATA_LOG_ALLOCATIONS
 extern char *strdupz(const char *s) MALLOCLIKE NEVERNULL;
 extern void *callocz(size_t nmemb, size_t size) MALLOCLIKE NEVERNULL;
 extern void *mallocz(size_t size) MALLOCLIKE NEVERNULL;
 extern void *reallocz(void *ptr, size_t size) MALLOCLIKE NEVERNULL;
 extern void freez(void *ptr);
-#endif
+#endif // NETDATA_LOG_ALLOCATIONS
 
 extern void json_escape_string(char *dst, const char *src, size_t size);
 extern void json_fix_string(char *s);
@@ -268,8 +249,6 @@ extern struct rlimit rlimit_nofile;
 
 extern int enable_ksm;
 
-extern int sleep_usec(usec_t usec);
-
 extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len);
 
 extern int verify_netdata_host_prefix();
@@ -306,4 +285,24 @@ extern void recursive_config_double_dir_load(
 extern void netdata_cleanup_and_exit(int ret) NORETURN;
 extern char *netdata_configured_host_prefix;
 
+#include "os.h"
+#include "storage_number/storage_number.h"
+#include "threads/threads.h"
+#include "buffer/buffer.h"
+#include "locks/locks.h"
+#include "avl/avl.h"
+#include "inlined.h"
+#include "clocks/clocks.h"
+#include "popen/popen.h"
+#include "simple_pattern/simple_pattern.h"
+#include "socket/socket.h"
+#include "config/appconfig.h"
+#include "log/log.h"
+#include "procfile/procfile.h"
+#include "dictionary/dictionary.h"
+#include "eval/eval.h"
+#include "statistical/statistical.h"
+#include "adaptive_resortable_list/adaptive_resortable_list.h"
+#include "url/url.h"
+
 #endif // NETDATA_LIB_H