]> arthur.barton.de Git - netdata.git/commitdiff
fix for self-kill
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Mon, 14 Sep 2015 18:26:50 +0000 (21:26 +0300)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Mon, 14 Sep 2015 18:26:50 +0000 (21:26 +0300)
src/main.c
src/main.h
src/plugins_d.c
src/popen.c

index 08c5d61ad541288ad4376bee66c8d768929aa90f..a8f090d37c22d7914357d6c6957d5af337b89ebf 100755 (executable)
@@ -60,6 +60,62 @@ struct netdata_static_thread static_threads[] = {
        {NULL,                  NULL,           NULL,                   0, NULL, NULL,  NULL}
 };
 
+int killpid(pid_t pid, int sig)
+{
+       int ret = -1;
+       debug(D_EXIT, "Request to kill pid %d", pid);
+
+       errno = 0;
+       if(kill(pid, 0) == -1) {
+               switch(errno) {
+                       case ESRCH: 
+                               error("Request to kill pid %d, but it is not running.", pid);
+                               break;
+
+                       case EPERM:
+                               error("Request to kill pid %d, but I do not have enough permissions.", pid);
+                               break;
+
+                       default:
+                               error("Request to kill pid %d, but I received an error.", pid);
+                               break;
+               }
+       }
+       else {
+               errno = 0;
+               
+               void (*old)(int);               
+               old = signal(sig, SIG_IGN);
+               if(old == SIG_ERR) {
+                       error("Cannot overwrite signal handler for signal %d", sig);
+                       old = sig_handler;
+               }
+
+               ret = kill(pid, sig);
+
+               if(signal(sig, old) == SIG_ERR)
+                       error("Cannot restore signal handler for signal %d", sig);
+
+               if(ret == -1) {
+                       switch(errno) {
+                               case ESRCH: 
+                                       error("Cannot kill pid %d, but it is not running.", pid);
+                                       break;
+
+                               case EPERM:
+                                       error("Cannot kill pid %d, but I do not have enough permissions.", pid);
+                                       break;
+
+                               default:
+                                       error("Cannot kill pid %d, but I received an error.", pid);
+                                       break;
+                       }
+               }
+       }
+
+       return ret;
+}
+
 void kill_childs()
 {
        siginfo_t info;
@@ -82,11 +138,9 @@ void kill_childs()
        }
 
        if(tc_child_pid) {
-               if(kill(tc_child_pid, 0) != -1) {
-                       info("Killing tc-qos-helper procees");
-                       kill(tc_child_pid, SIGTERM);
+               info("Killing tc-qos-helper procees");
+               if(killpid(tc_child_pid, SIGTERM) != -1)
                        waitid(tc_child_pid, 0, &info, WEXITED);
-               }
        }
        tc_child_pid = 0;
 
@@ -97,11 +151,9 @@ void kill_childs()
                pthread_join(cd->thread, NULL);
 
                if(cd->pid && !cd->obsolete) {
-                       if(kill(cd->pid, 0) != -1) {
-                               debug(D_EXIT, "killing %s plugin process", cd->id);
-                               kill(cd->pid, SIGTERM);
+                       debug(D_EXIT, "killing %s plugin process", cd->id);
+                       if(killpid(cd->pid, SIGTERM) != -1)
                                waitid(cd->pid, 0, &info, WEXITED);
-                       }
                }
        }
 
index 7914ecc6b20dbaee528d9e5e6f795836c73d2fd6..d6b3107102be9a6f4a1b7e044cfc7a1f664d3f51 100755 (executable)
@@ -2,5 +2,6 @@
 #define NETDATA_MAIN_H 1
 
 extern void kill_childs(void);
+extern int killpid(pid_t pid, int signal);
 
 #endif /* NETDATA_MAIN_H */
index 2fe5c56baf6bed014f96e0d2a8048f5a866ad9b1..11f26edd259407cdd72c761fd0c020ec502cc3a1 100755 (executable)
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <signal.h>
 
+#include "main.h"
 #include "common.h"
 #include "config.h"
 #include "log.h"
@@ -124,6 +125,8 @@ void *pluginsd_worker_thread(void *arg)
                        break;
                }
 
+               info("PLUGINSD: '%s' running on pid %d", cd->fullfilename, cd->pid);
+
                RRDSET *st = NULL;
                unsigned long long count = 0;
                char *s;
@@ -152,8 +155,7 @@ void *pluginsd_worker_thread(void *arg)
                                if(!dimension || !*dimension) {
                                        error("PLUGINSD: '%s' is requesting a SET on chart '%s', like this: 'SET %s = %s'. Disabling it.", cd->fullfilename, st->id, dimension?dimension:"<nothing>", value?value:"<nothing>");
                                        cd->enabled = 0;
-                                       // test: killing an exited child kills us - lets check it exists before killing it
-                                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                                       killpid(cd->pid, SIGTERM);
                                        break;
                                }
 
@@ -162,8 +164,7 @@ void *pluginsd_worker_thread(void *arg)
                                if(!st) {
                                        error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s, without a BEGIN. Disabling it.", cd->fullfilename, dimension, value);
                                        cd->enabled = 0;
-                                       // test: killing an exited child kills us - lets check it exists before killing it
-                                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                                       killpid(cd->pid, SIGTERM);
                                        break;
                                }
 
@@ -179,8 +180,7 @@ void *pluginsd_worker_thread(void *arg)
                                if(!id) {
                                        error("PLUGINSD: '%s' is requesting a BEGIN without a chart id. Disabling it.", cd->fullfilename);
                                        cd->enabled = 0;
-                                       // test: killing an exited child kills us - lets check it exists before killing it
-                                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                                       killpid(cd->pid, SIGTERM);
                                        break;
                                }
 
@@ -188,8 +188,7 @@ void *pluginsd_worker_thread(void *arg)
                                if(!st) {
                                        error("PLUGINSD: '%s' is requesting a BEGIN on chart '%s', which does not exist. Disabling it.", cd->fullfilename, id);
                                        cd->enabled = 0;
-                                       // test: killing an exited child kills us - lets check it exists before killing it
-                                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                                       killpid(cd->pid, SIGTERM);
                                        break;
                                }
 
@@ -204,8 +203,7 @@ void *pluginsd_worker_thread(void *arg)
                                if(!st) {
                                        error("PLUGINSD: '%s' is requesting an END, without a BEGIN. Disabling it.", cd->fullfilename);
                                        cd->enabled = 0;
-                                       // test: killing an exited child kills us - lets check it exists before killing it
-                                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                                       killpid(cd->pid, SIGTERM);
                                        break;
                                }
 
@@ -239,8 +237,7 @@ void *pluginsd_worker_thread(void *arg)
                                if(!type || !*type || !id || !*id) {
                                        error("PLUGINSD: '%s' is requesting a CHART, without a type.id. Disabling it.", cd->fullfilename);
                                        cd->enabled = 0;
-                                       // test: killing an exited child kills us - lets check it exists before killing it
-                                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                                       killpid(cd->pid, SIGTERM);
                                        break;
                                }
 
@@ -288,16 +285,14 @@ void *pluginsd_worker_thread(void *arg)
                                if(!id || !*id) {
                                        error("PLUGINSD: '%s' is requesting a DIMENSION, without an id. Disabling it.", cd->fullfilename);
                                        cd->enabled = 0;
-                                       // test: killing an exited child kills us - lets check it exists before killing it
-                                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                                       killpid(cd->pid, SIGTERM);
                                        break;
                                }
 
                                if(!st) {
                                        error("PLUGINSD: '%s' is requesting a DIMENSION, without a CHART. Disabling it.", cd->fullfilename);
                                        cd->enabled = 0;
-                                       // test: killing an exited child kills us - lets check it exists before killing it
-                                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                                       killpid(cd->pid, SIGTERM);
                                        break;
                                }
 
@@ -331,8 +326,7 @@ void *pluginsd_worker_thread(void *arg)
                        else if(hash == DISABLE_HASH && !strcmp(s, "DISABLE")) {
                                error("PLUGINSD: '%s' called DISABLE. Disabling it.", cd->fullfilename);
                                cd->enabled = 0;
-                               // test: killing an exited child kills us - lets check it exists before killing it
-                               if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                               killpid(cd->pid, SIGTERM);
                                break;
                        }
 #ifdef DETACH_PLUGINS_FROM_NETDATA
@@ -361,8 +355,7 @@ void *pluginsd_worker_thread(void *arg)
 
                                error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
                                usleep(susec);
-                               // test: killing an exited child kills us - lets check it exists before killing it
-                               if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGCONT);
+                               killpid(cd->pid, SIGCONT);
                                bcopy(&now, &last, sizeof(struct timeval));
                                break;
                        }
@@ -370,23 +363,23 @@ void *pluginsd_worker_thread(void *arg)
                        else {
                                error("PLUGINSD: '%s' is sending command '%s' which is not known by netdata. Disabling it.", cd->fullfilename, s);
                                cd->enabled = 0;
-                               // test: killing an exited child kills us - lets check it exists before killing it
-                               if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                               killpid(cd->pid, SIGTERM);
                                break;
                        }
                }
 
+               info("PLUGINSD: '%s' on pid %d stopped.", cd->fullfilename, cd->pid);
+
                // fgets() failed or loop broke
                mypclose(fp, cd->pid);
-               cd->pid = 0;
 
                if(!count && cd->enabled) {
-                       error("PLUGINSD: '%s' does not generate usefull output. Disabling it.", cd->fullfilename);
-                       cd->enabled = 0;
-                       // test: killing an exited child kills us - lets check it exists before killing it
-                       if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
+                       error("PLUGINSD: '%s' (pid %d) does not generate usefull output. Waiting a bit before starting it again.", cd->fullfilename, cd->pid);
+                       sleep(cd->update_every * 10);
                }
 
+               cd->pid = 0;
+
                if(cd->enabled) sleep(cd->update_every);
                else break;
        }
index 279373b49f78baf88f4bf940afa7d292f56f1a13..aaaf6b47daf0c6e3f885a121588075fc7a2017ee 100755 (executable)
@@ -117,6 +117,8 @@ FILE *mypopen(const char *command, pid_t *pidptr)
 }
 
 void mypclose(FILE *fp, pid_t pid) {
+       debug(D_EXIT, "Request to mypclose() on pid %d", pid);
+       
        /*mypopen_del(fp);*/
        fclose(fp);