]> arthur.barton.de Git - netdata.git/commitdiff
various apps.plugin fixes - now it detects new processes on the fly; attempt to work...
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Mon, 5 May 2014 23:59:59 +0000 (02:59 +0300)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Mon, 5 May 2014 23:59:59 +0000 (02:59 +0300)
apps_plugin.c
netdata.c
plugins.d/charts.d.plugin

index a75a8eb688f0a9ad94d4321e408c83350fd1decc..b3e6c119a6a0c0981760411b474bdcbbb2dc445a 100755 (executable)
@@ -22,6 +22,7 @@
 #include <arpa/inet.h>\r
 \r
 #define MAX_COMPARE_NAME 15\r
+#define MAX_NAME 100\r
 \r
 \r
 #define add_childs 1ULL\r
@@ -33,8 +34,8 @@ int debug = 0;
 \r
 struct wanted {\r
        char compare[MAX_COMPARE_NAME + 3];\r
-       char id[FILENAME_MAX+1];\r
-       char name[FILENAME_MAX+1];\r
+       char id[MAX_NAME + 1];\r
+       char name[MAX_NAME + 1];\r
 \r
        unsigned long long minflt;\r
        unsigned long long cminflt;\r
@@ -48,10 +49,11 @@ struct wanted {
        unsigned long long rss;\r
 \r
        unsigned long merge_count;      // how many processes have been merged to this\r
+       int exposed;                            // if set, we have sent this to netdata\r
 \r
        struct wanted *target;  // the one that will be reported to netdata\r
        struct wanted *next;\r
-} *wanted_root = NULL;\r
+} *wanted_root = NULL, *default_target = NULL;\r
 \r
 int update_every = 1;\r
 \r
@@ -63,8 +65,8 @@ struct wanted *add_wanted(const char *id, struct wanted *target)
                return NULL;\r
        }\r
 \r
-       strncpy(w->id, id, FILENAME_MAX);\r
-       strncpy(w->name, id, FILENAME_MAX);\r
+       strncpy(w->id, id, MAX_NAME);\r
+       strncpy(w->name, id, MAX_NAME);\r
        snprintf(w->compare, MAX_COMPARE_NAME+1, "(%.*s)", MAX_COMPARE_NAME, id);\r
        w->target = target;\r
 \r
@@ -99,7 +101,7 @@ void parse_args(int argc, char **argv)
 \r
                while((t = strsep(&s, " "))) {\r
                        if(w && strcmp(t, "as") == 0 && s && *s) {\r
-                               strncpy(w->name, s, FILENAME_MAX);\r
+                               strncpy(w->name, s, MAX_NAME);\r
                                if(debug) fprintf(stderr, "Setting dimension name to '%s' on target '%s'\n", w->name, w->id);\r
                                break;\r
                        }\r
@@ -108,12 +110,15 @@ void parse_args(int argc, char **argv)
                        if(!w) w = n;\r
                }\r
        }\r
+\r
+       default_target = add_wanted("all_other_processes", NULL);\r
+       strncpy(default_target->name, "other", MAX_NAME);\r
 }\r
 \r
 // see: man proc\r
 struct pid_stat {\r
        int32_t pid;\r
-       char comm[FILENAME_MAX+1];\r
+       char comm[MAX_COMPARE_NAME + 3];\r
        char state;\r
        int32_t ppid;\r
        int32_t pgrp;\r
@@ -163,6 +168,7 @@ struct pid_stat {
        int new_entry;\r
        unsigned long merge_count;\r
        struct wanted *target;\r
+       int target_inherited;\r
        struct pid_stat *parent;\r
        struct pid_stat *prev;\r
        struct pid_stat *next;\r
@@ -209,6 +215,7 @@ void del_entry(pid_t pid)
 int update_from_proc(void)\r
 {\r
        char buffer[PID_STAT_LINE_MAX + 1];\r
+       char name[PID_STAT_LINE_MAX + 1];\r
        char filename[FILENAME_MAX+1];\r
        DIR *dir = opendir("/proc");\r
        if(!dir) return 0;\r
@@ -224,6 +231,8 @@ int update_from_proc(void)
                p->merged = 0;\r
                p->new_entry = 0;\r
                p->merge_count = 0;\r
+\r
+               if(p->target_inherited) p->target = NULL;\r
        }\r
 \r
        while((file = readdir(dir))) {\r
@@ -269,7 +278,7 @@ int update_from_proc(void)
                        " %d %d"                                                        // exit_signal, processor\r
                        " %u %u"                                                        // rt_priority, policy\r
                        " %llu %lu %ld"\r
-                       , &p->pid, p->comm, &p->state\r
+                       , &p->pid, name, &p->state\r
                        , &p->ppid, &p->pgrp, &p->session, &p->tty_nr, &p->tpgid\r
                        , &p->flags, &p->minflt, &p->cminflt, &p->majflt, &p->cmajflt\r
                        , &p->utime, &p->stime, &p->cutime, &p->cstime\r
@@ -286,6 +295,8 @@ int update_from_proc(void)
                        , &p->rt_priority, &p->policy\r
                        , &p->delayacct_blkio_ticks, &p->guest_time, &p->cguest_time\r
                        );\r
+               strncpy(p->comm, name, MAX_COMPARE_NAME + 2);\r
+               p->comm[MAX_COMPARE_NAME + 2] = '\0';\r
 \r
                if(parsed < 39) fprintf(stderr, "file %s gave %d results (expected 44)\n", filename, parsed);\r
 \r
@@ -335,7 +346,7 @@ void merge_processes(void)
 {\r
        struct pid_stat *p = NULL;\r
 \r
-       // link all parents and update childs\r
+       // link all parents and update childs count\r
        for(p = root; p ; p = p->next) {\r
                if(p->ppid > 1 && p->ppid <= pid_max && all_pids[p->ppid]) {\r
                        if(debug) fprintf(stderr, "\tParent of %d %s is %d %s\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm);\r
@@ -350,13 +361,18 @@ void merge_processes(void)
                }\r
        }\r
 \r
-       // find all the procs with 0 childs and update their parents\r
-       // continue, until nothing more can be done.\r
+       // find all the procs with 0 childs and merge them to their parents\r
+       // repeat, until nothing more can be done.\r
        int found = 1;\r
        for( ; found ; ) {\r
                found = 0;\r
                for(p = root; p ; p = p->next) {\r
-                       if(!p->childs && !p->merged && p->parent && p->parent->childs) {\r
+                       // if this process does not any childs, and\r
+                       // is not already merged, and\r
+                       // its parents has childs waiting to be merged, and\r
+                       // the target of this process and its parent is the same, or the parent does not have a target, or this process does not have a parent\r
+                       // then... merge them!\r
+                       if(!p->childs && !p->merged && p->parent && p->parent->childs && (p->target == p->parent->target || !p->parent->target || !p->target)) {\r
                                if(debug) fprintf(stderr, "\tMerging %d %s to %d %s (count: %lu)\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm, p->parent->merge_count+1);\r
 \r
                                p->parent->minflt += p->minflt;\r
@@ -380,7 +396,8 @@ void merge_processes(void)
                                // the parent inherits the child's target, if it does not have a target itself\r
                                if(p->target && !p->parent->target) {\r
                                        p->parent->target = p->target;\r
-                                       if(debug) fprintf(stderr, "\t\ttarget %s is inherited from %d %s by its child %d %s.\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);\r
+                                       p->parent->target_inherited = 1;\r
+                                       if(debug) fprintf(stderr, "\t\ttarget %s is inherited by %d %s from its child %d %s.\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);\r
                                }\r
 \r
                                found++;\r
@@ -416,21 +433,29 @@ void merge_processes(void)
 \r
        // concentrate everything on the targets\r
        for(p = root; p ; p = p->next) {\r
-               if(!p->childs && !p->merged && !p->parent && p->target) {\r
-                       p->target->minflt += p->minflt;\r
-                       p->target->majflt += p->majflt;\r
-                       p->target->utime += p->utime;\r
-                       p->target->stime += p->stime;\r
-                       p->target->cminflt += p->cminflt;\r
-                       p->target->cmajflt += p->cmajflt;\r
-                       p->target->cutime += p->cutime;\r
-                       p->target->cstime += p->cstime;\r
-                       p->target->num_threads += p->num_threads;\r
-                       p->target->rss += p->rss;\r
-\r
-                       p->target->merge_count += p->merge_count + 1;\r
-                       if(debug) fprintf(stderr, "\tAgregating %s pid %d on %s (count: %lu)\n", p->comm, p->pid, p->target->name, p->target->merge_count);\r
+               if(p->parent && !p->merged) fprintf(stderr, "\tprocess %s pid %d has a parent, but has not been merged!\n", p->comm, p->pid);\r
+               if(p->childs) fprintf(stderr, "\tprocess %s pid %d has %d childs that have not been merged!\n", p->comm, p->pid, p->childs);\r
+               if(p->merged) continue;\r
+\r
+               if(!p->target) {\r
+                       p->target = default_target;\r
+                       p->target_inherited = 1;\r
+                       if(debug) fprintf(stderr, "\tprocess %s pid %d is orphan\n", p->comm, p->pid);\r
                }\r
+\r
+               p->target->minflt += p->minflt;\r
+               p->target->majflt += p->majflt;\r
+               p->target->utime += p->utime;\r
+               p->target->stime += p->stime;\r
+               p->target->cminflt += p->cminflt;\r
+               p->target->cmajflt += p->cmajflt;\r
+               p->target->cutime += p->cutime;\r
+               p->target->cstime += p->cstime;\r
+               p->target->num_threads += p->num_threads;\r
+               p->target->rss += p->rss;\r
+\r
+               p->target->merge_count += p->merge_count + 1;\r
+               if(debug) fprintf(stderr, "\tAgregating %s pid %d on %s (count: %lu)\n", p->comm, p->pid, p->target->name, p->target->merge_count);\r
        }\r
 }\r
 \r
@@ -441,7 +466,7 @@ void show_dimensions(void)
 \r
        fprintf(stdout, "BEGIN apps.cpu\n");\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime + (w->cutime * add_childs) + (w->cstime * add_childs));\r
        }\r
@@ -449,7 +474,7 @@ void show_dimensions(void)
 \r
        fprintf(stdout, "BEGIN apps.cpu_user\n");\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + (w->cutime * add_childs));\r
        }\r
@@ -457,7 +482,7 @@ void show_dimensions(void)
 \r
        fprintf(stdout, "BEGIN apps.cpu_system\n");\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "SET %s = %llu\n", w->name, w->stime + (w->cstime * add_childs));\r
        }\r
@@ -465,7 +490,7 @@ void show_dimensions(void)
 \r
        fprintf(stdout, "BEGIN apps.threads\n");\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "SET %s = %llu\n", w->name, w->num_threads);\r
        }\r
@@ -473,7 +498,7 @@ void show_dimensions(void)
 \r
        fprintf(stdout, "BEGIN apps.processes\n");\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "SET %s = %lu\n", w->name, w->merge_count);\r
        }\r
@@ -481,7 +506,7 @@ void show_dimensions(void)
 \r
        fprintf(stdout, "BEGIN apps.rss\n");\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "SET %s = %llu\n", w->name, (unsigned long long)w->rss);\r
        }\r
@@ -489,7 +514,7 @@ void show_dimensions(void)
 \r
        fprintf(stdout, "BEGIN apps.minor_faults\n");\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt + (w->cminflt * add_childs));\r
        }\r
@@ -497,7 +522,7 @@ void show_dimensions(void)
 \r
        fprintf(stdout, "BEGIN apps.major_faults\n");\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt + (w->cmajflt * add_childs));\r
        }\r
@@ -509,59 +534,72 @@ void show_dimensions(void)
 void show_charts(void)\r
 {\r
        struct wanted *w;\r
+       int newly_added = 0;\r
 \r
+       for(w = wanted_root ; w ; w = w->next)\r
+               if(!w->exposed && w->merge_count) {\r
+                       newly_added++;\r
+                       w->exposed = 1;\r
+                       if(debug) fprintf(stderr, "%s just added - regenerating charts.\n", w->name);\r
+               }\r
+\r
+       // nothing more to show\r
+       if(!newly_added) return;\r
+\r
+       // we have something new to show\r
+       // update the charts\r
        fprintf(stdout, "CHART apps.cpu '' 'Applications CPU Time' 'cpu time %%' apps apps stacked 20001 %d\n", update_every);\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz);\r
        }\r
 \r
        fprintf(stdout, "CHART apps.rss '' 'Applications Memory' 'MB' apps apps stacked 20002 %d\n", update_every);\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);\r
        }\r
 \r
        fprintf(stdout, "CHART apps.threads '' 'Applications Threads' 'threads' apps apps stacked 20005 %d\n", update_every);\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);\r
        }\r
 \r
        fprintf(stdout, "CHART apps.processes '' 'Applications Processes' 'processes' apps apps stacked 20004 %d\n", update_every);\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);\r
        }\r
 \r
        fprintf(stdout, "CHART apps.cpu_user '' 'Applications CPU User Time' 'cpu time %%' apps none stacked 20020 %d\n", update_every);\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz);\r
        }\r
 \r
        fprintf(stdout, "CHART apps.cpu_system '' 'Applications CPU System Time' 'cpu time %%' apps none stacked 20021 %d\n", update_every);\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz);\r
        }\r
 \r
        fprintf(stdout, "CHART apps.major_faults '' 'Applications Major Page Faults' 'page faults/s' apps apps stacked 20010 %d\n", update_every);\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w->name);\r
        }\r
 \r
        fprintf(stdout, "CHART apps.minor_faults '' 'Applications Minor Page Faults' 'page faults/s' apps apps stacked 20011 %d\n", update_every);\r
        for (w = wanted_root; w ; w = w->next) {\r
-               if(w->target) continue;\r
+               if(w->target || (!w->merge_count && !w->exposed)) continue;\r
 \r
                fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w->name);\r
        }\r
@@ -633,8 +671,6 @@ int main(int argc, char **argv)
                exit(1);\r
        }\r
 \r
-       show_charts();\r
-\r
        unsigned long long counter = 1;\r
        unsigned long long usec = 0, susec = 0;\r
        struct timeval last, now;\r
@@ -648,6 +684,7 @@ int main(int argc, char **argv)
                }\r
 \r
                merge_processes();\r
+               show_charts();          // this is smart enough to show only newly added apps, when needed\r
                show_dimensions();\r
 \r
                if(debug) fprintf(stderr, "Done Loop No %llu\n", counter);\r
index ccddbe36d4b772f4932fb2f561d6fc709b1f51b0..81bf4e1c291f0fc0f3ab97afaf0d9a9e4ade30ea 100644 (file)
--- a/netdata.c
+++ b/netdata.c
@@ -313,15 +313,38 @@ FILE *mypopen(const char *command, pid_t *pidptr)
        for(i = sysconf(_SC_OPEN_MAX); i > 0; i--)
                if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i);
 
-       // ignore all signals
-       for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i, SIG_DFL);
-
        // move the pipe to stdout
        if(pipefd[PIPE_WRITE] != STDOUT_FILENO) {
                dup2(pipefd[PIPE_WRITE], STDOUT_FILENO);
                close(pipefd[PIPE_WRITE]);
        }
 
+/*
+       // fork again to become session leader
+       pid = fork();
+       if(pid == -1) fprintf(stderr, "Cannot fork again on pid %d\n", getpid());
+       if(pid != 0) {
+               // the parent
+               exit(0);
+       }
+
+       // set a new process group id for just this child
+       if( setpgid(0, 0) != 0 )
+               fprintf(stderr, "Cannot set a new process group for pid %d (%s)\n", getpid(), strerror(errno));
+
+       if( getpgid(0) != getpid() )
+               fprintf(stderr, "Process group set is incorrect. Expected %d, found %d\n", getpid(), getpgid(0));
+
+       if( setsid() != 0 )
+               fprintf(stderr, "Cannot set session id for pid %d (%s)\n", getpid(), strerror(errno));
+*/
+       
+       // ignore all signals
+       for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i, SIG_DFL);
+
+       fprintf(stdout, "MYPID %d\n", getpid());
+       fflush(NULL);
+
        fprintf(stderr, "executing command: '%s'\n", command);
        execl("/bin/sh", "sh", "-c", command, NULL);
        exit(1);
@@ -5533,6 +5556,8 @@ void *tc_main(void *ptr)
                                if(pid != tc_child_pid)
                                        error("tc-qos-helper reports wrong pid %d (expected %d).", pid, tc_child_pid);
 
+                               // tc_child_pid = pid;
+
                                debug(D_TC_LOOP, "TC: Child PID is %d.", tc_child_pid);
                        }
                }
@@ -5664,6 +5689,9 @@ void *pluginsd_worker_thread(void *arg)
        struct plugind *cd = (struct plugind *)arg;
        char line[PLUGINSD_LINE_MAX + 1];
 
+       unsigned long long usec = 0, susec = 0;
+       struct timeval last, now;
+
        while(1) {
                // FILE *fp = popen(cd->cmd, "r");
                FILE *fp = mypopen(cd->cmd, &cd->pid);
@@ -5863,6 +5891,7 @@ void *pluginsd_worker_thread(void *arg)
                                        kill(cd->pid, SIGTERM);
                                        break;
                                }
+                               // cd->pid = pid;
 
                                debug(D_PLUGINSD, "PLUGINSD: %s is on pid %d", cd->id, cd->pid);
                        }
@@ -5872,6 +5901,28 @@ void *pluginsd_worker_thread(void *arg)
                                kill(cd->pid, SIGTERM);
                                break;
                        }
+                       else if(!strcmp(s, "STOPPING_WAKE_ME_UP_PLEASE")) {
+                               error("PLUGINSD: script '%s' (pid %d) called STOPPING_WAKE_ME_UP_PLEASE.", cd->fullfilename, cd->pid);
+
+                               gettimeofday(&now, NULL);
+                               if(!usec && !susec) {
+                                       // our first run
+                                       susec = cd->update_every * 1000000ULL;
+                               }
+                               else {
+                                       // second+ run
+                                       usec = usecdiff(&now, &last) - susec;
+                                       error("PLUGINSD: %s last loop took %llu usec (worked for %llu, sleeped for %llu).\n", cd->fullfilename, usec + susec, usec, susec);
+                                       if(usec < (update_every * 1000000ULL)) susec = (update_every * 1000000ULL) - usec;
+                                       else susec = 100000ULL;
+                               }
+
+                               error("PLUGINSD: %s sleeping for %llu. Will kill pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
+                               usleep(susec);
+                               kill(cd->pid, SIGCONT);
+                               bcopy(&now, &last, sizeof(struct timeval));
+                               break;
+                       }
                        else {
                                error("PLUGINSD: script %s is sending command '%s' which is not known by netdata. Disabling it.", cd->fullfilename, s);
                                cd->enabled = 0;
@@ -5961,7 +6012,39 @@ void *pluginsd_main(void *ptr)
                                cd->update_every = config_get_number(cd->id, "update every", update_every);
 
                                char *def = "";
-                               if(strcmp(cd->id, "plugin:apps") == 0) def = "mplayer squid 'apache apache2 as apache' mysqld asterisk dovecot 'master as postfix' 'smbd nmbd as samba' sshd 'gdm as X' named 'clamd freshclam as clam' 'cupsd as cups' 'ntpd as ntp' 'deluge deluged as deluge' netdata";
+                               if(strcmp(cd->id, "plugin:apps") == 0)
+                                       def =
+                                       " 'mplayer vlc xine mediatomb as media'"
+                                       " 'squid squid3 as squid'"
+                                       " 'apache apache2 as apache'"
+                                       " 'mysql mysqld as mysql'"
+                                       " asterisk"
+                                       " opensips"
+                                       " dovecot"
+                                       " nginx"
+                                       " lighttpd"
+                                       " 'proftpd in.tftpd as ftpd'"
+                                       " 'master as postfix'"
+                                       " 'smbd nmbd winbindd as samba'"
+                                       " 'rpcbind rpc.statd rpc.idmapd rpc.mountd as nfs'"
+                                       " 'ssh sshd as ssh'"
+                                       " 'gdm X lightdm xdm gnome-session gconfd-2 gnome-terminal gnome-screensaver gnome-settings-daemon pulseaudio as X'"
+                                       " 'named as bind'"
+                                       " 'clamd freshclam as clam'"
+                                       " 'cupsd cups-browsed as cups'"
+                                       " 'ntpq ntpd as ntp'"
+                                       " 'deluge deluged as deluge'"
+                                       " 'vboxwebsrv VBoxXPCOMIPCD VBoxSVC as vbox'"
+                                       " 'ulogd syslogd syslog-ng rsyslogd logrotate as log'"
+                                       " 'snmpd vnstatd smokeping zabbix_agentd monit munin-node mon as nms'"
+                                       " 'ppp pppd pptpd pptpctrl as ppp'"
+                                       " 'inetd xinetd as inetd'"
+                                       " openvpn"
+                                       " 'cron atd as cron'"
+                                       " 'corosync hs_logd stonithd as ha'"
+                                       " 'ipvs_syncmaster ipvs_syncbackup as ipvs'"
+                                       " netdata"
+                                       ;
                                snprintf(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def));
 
                                // link it
@@ -6005,13 +6088,6 @@ void kill_childs()
                }
 }
 
-void bye(void)
-{
-       error("exiting. bye...");
-       kill_childs();
-       tc_child_pid = 0;
-}
-
 void sig_handler(int signo)
 {
        switch(signo) {
@@ -6421,8 +6497,6 @@ int main(int argc, char **argv)
 
        error("NetData started on pid %d", getpid());
 
-       // make sure we cleanup correctly
-       atexit(bye);
 
        // catch all signals
        for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i,  sig_handler);
index 310402824034dae9b2e2076b8fb6919f6202ebe4..635f2a2bbbd5796f781626471d991e626cd4c6d0 100755 (executable)
@@ -3,6 +3,10 @@
 # -----------------------------------------------------------------------------
 # insternal defaults
 
+pause_method="sleep" # use either "suspend" or "sleep"
+                     # DO NOT USE SUSPEND - LINUX WILL SUSPEND NETDATA TOO
+                     # THE WHOLE PROCESS GROUP - NOT JUST THE SHELL
+
 pluginsd="plugins.d"
 confd="conf.d"
 chartsd="charts.d"
@@ -86,6 +90,12 @@ if [ -f "$myconfig" ]
        fi
 fi
 
+if [ "$pause_method" = "suspend" ]
+then
+       # enable bash job control
+       # this is required for suspend to work
+       set -m
+fi
 
 # -----------------------------------------------------------------------------
 # internal checks
@@ -275,6 +285,12 @@ do
                fi
        done
 
-       # wait the time you are required to
-       loopsleepms $debug_time $update_every
+       if [ "$pause_method" = "suspend" ]
+       then
+               echo "STOPPING_WAKE_ME_UP_PLEASE"
+               suspend || ( echo >&2 "suspend returned error $?, falling back to sleep."; loopsleepms $debug_time $update_every )
+       else
+               # wait the time you are required to
+               loopsleepms $debug_time $update_every
+       fi
 done