fix for self-kill
Costa Tsaousis (ktsaou) committed
Sep 14, 2015 at 21:26 UTC
ed321f3f375edd6154f895a434682c006b27a1c2
4 files changed
+83
-35
src/main.c
+60
-8
@@ -60,6 +60,62 @@ struct netdata_static_thread static_threads[] = {
60
{NULL, NULL, NULL, 0, NULL, NULL, NULL}
61
};
62
63
+int killpid(pid_t pid, int sig)
64
+{
65
+ int ret = -1;
66
+ debug(D_EXIT, "Request to kill pid %d", pid);
67
+
68
+ errno = 0;
69
+ if(kill(pid, 0) == -1) {
70
+ switch(errno) {
71
+ case ESRCH:
72
+ error("Request to kill pid %d, but it is not running.", pid);
73
+ break;
74
+
75
+ case EPERM:
76
+ error("Request to kill pid %d, but I do not have enough permissions.", pid);
77
+ break;
78
+
79
+ default:
80
+ error("Request to kill pid %d, but I received an error.", pid);
81
+ break;
82
+ }
83
+ }
84
+ else {
85
+ errno = 0;
86
+
87
+ void (*old)(int);
88
+ old = signal(sig, SIG_IGN);
89
+ if(old == SIG_ERR) {
90
+ error("Cannot overwrite signal handler for signal %d", sig);
91
+ old = sig_handler;
92
+ }
93
+
94
+ ret = kill(pid, sig);
95
+
96
+ if(signal(sig, old) == SIG_ERR)
97
+ error("Cannot restore signal handler for signal %d", sig);
98
+
99
+ if(ret == -1) {
100
+ switch(errno) {
101
+ case ESRCH:
102
+ error("Cannot kill pid %d, but it is not running.", pid);
103
+ break;
104
+
105
+ case EPERM:
106
+ error("Cannot kill pid %d, but I do not have enough permissions.", pid);
107
+ break;
108
+
109
+ default:
110
+ error("Cannot kill pid %d, but I received an error.", pid);
111
+ break;
112
+ }
113
+ }
114
+ }
115
+
116
+ return ret;
117
+}
118
+
119
void kill_childs()
120
{
121
siginfo_t info;
@@ -82,11 +138,9 @@ void kill_childs()
138
}
139
140
if(tc_child_pid) {
85
- if(kill(tc_child_pid, 0) != -1) {
86
- info("Killing tc-qos-helper procees");
87
- kill(tc_child_pid, SIGTERM);
141
+ info("Killing tc-qos-helper procees");
142
+ if(killpid(tc_child_pid, SIGTERM) != -1)
143
waitid(tc_child_pid, 0, &info, WEXITED);
89
- }
144
}
145
tc_child_pid = 0;
146
@@ -97,11 +151,9 @@ void kill_childs()
151
pthread_join(cd->thread, NULL);
152
153
if(cd->pid && !cd->obsolete) {
100
- if(kill(cd->pid, 0) != -1) {
101
- debug(D_EXIT, "killing %s plugin process", cd->id);
102
- kill(cd->pid, SIGTERM);
154
+ debug(D_EXIT, "killing %s plugin process", cd->id);
155
+ if(killpid(cd->pid, SIGTERM) != -1)
156
waitid(cd->pid, 0, &info, WEXITED);
104
- }
157
}
158
}
159
src/main.h
+1
@@ -2,5 +2,6 @@
2
#define NETDATA_MAIN_H 1
3
4
extern void kill_childs(void);
5
+extern int killpid(pid_t pid, int signal);
6
7
#endif /* NETDATA_MAIN_H */
src/plugins_d.c
+20
-27
@@ -6,6 +6,7 @@
6
#include <stdlib.h>
7
#include <signal.h>
8
9
+#include "main.h"
10
#include "common.h"
11
#include "config.h"
12
#include "log.h"
@@ -124,6 +125,8 @@ void *pluginsd_worker_thread(void *arg)
125
break;
126
}
127
128
+ info("PLUGINSD: '%s' running on pid %d", cd->fullfilename, cd->pid);
129
+
130
RRDSET *st = NULL;
131
unsigned long long count = 0;
132
char *s;
@@ -152,8 +155,7 @@ void *pluginsd_worker_thread(void *arg)
155
if(!dimension || !*dimension) {
156
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>");
157
cd->enabled = 0;
155
- // test: killing an exited child kills us - lets check it exists before killing it
156
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
158
+ killpid(cd->pid, SIGTERM);
159
break;
160
}
161
@@ -162,8 +164,7 @@ void *pluginsd_worker_thread(void *arg)
164
if(!st) {
165
error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s, without a BEGIN. Disabling it.", cd->fullfilename, dimension, value);
166
cd->enabled = 0;
165
- // test: killing an exited child kills us - lets check it exists before killing it
166
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
167
+ killpid(cd->pid, SIGTERM);
168
break;
169
}
170
@@ -179,8 +180,7 @@ void *pluginsd_worker_thread(void *arg)
180
if(!id) {
181
error("PLUGINSD: '%s' is requesting a BEGIN without a chart id. Disabling it.", cd->fullfilename);
182
cd->enabled = 0;
182
- // test: killing an exited child kills us - lets check it exists before killing it
183
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
183
+ killpid(cd->pid, SIGTERM);
184
break;
185
}
186
@@ -188,8 +188,7 @@ void *pluginsd_worker_thread(void *arg)
188
if(!st) {
189
error("PLUGINSD: '%s' is requesting a BEGIN on chart '%s', which does not exist. Disabling it.", cd->fullfilename, id);
190
cd->enabled = 0;
191
- // test: killing an exited child kills us - lets check it exists before killing it
192
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
191
+ killpid(cd->pid, SIGTERM);
192
break;
193
}
194
@@ -204,8 +203,7 @@ void *pluginsd_worker_thread(void *arg)
203
if(!st) {
204
error("PLUGINSD: '%s' is requesting an END, without a BEGIN. Disabling it.", cd->fullfilename);
205
cd->enabled = 0;
207
- // test: killing an exited child kills us - lets check it exists before killing it
208
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
206
+ killpid(cd->pid, SIGTERM);
207
break;
208
}
209
@@ -239,8 +237,7 @@ void *pluginsd_worker_thread(void *arg)
237
if(!type || !*type || !id || !*id) {
238
error("PLUGINSD: '%s' is requesting a CHART, without a type.id. Disabling it.", cd->fullfilename);
239
cd->enabled = 0;
242
- // test: killing an exited child kills us - lets check it exists before killing it
243
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
240
+ killpid(cd->pid, SIGTERM);
241
break;
242
}
243
@@ -288,16 +285,14 @@ void *pluginsd_worker_thread(void *arg)
285
if(!id || !*id) {
286
error("PLUGINSD: '%s' is requesting a DIMENSION, without an id. Disabling it.", cd->fullfilename);
287
cd->enabled = 0;
291
- // test: killing an exited child kills us - lets check it exists before killing it
292
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
288
+ killpid(cd->pid, SIGTERM);
289
break;
290
}
291
292
if(!st) {
293
error("PLUGINSD: '%s' is requesting a DIMENSION, without a CHART. Disabling it.", cd->fullfilename);
294
cd->enabled = 0;
299
- // test: killing an exited child kills us - lets check it exists before killing it
300
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
295
+ killpid(cd->pid, SIGTERM);
296
break;
297
}
298
@@ -331,8 +326,7 @@ void *pluginsd_worker_thread(void *arg)
326
else if(hash == DISABLE_HASH && !strcmp(s, "DISABLE")) {
327
error("PLUGINSD: '%s' called DISABLE. Disabling it.", cd->fullfilename);
328
cd->enabled = 0;
334
- // test: killing an exited child kills us - lets check it exists before killing it
335
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
329
+ killpid(cd->pid, SIGTERM);
330
break;
331
}
332
#ifdef DETACH_PLUGINS_FROM_NETDATA
@@ -361,8 +355,7 @@ void *pluginsd_worker_thread(void *arg)
355
356
error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
357
usleep(susec);
364
- // test: killing an exited child kills us - lets check it exists before killing it
365
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGCONT);
358
+ killpid(cd->pid, SIGCONT);
359
bcopy(&now, &last, sizeof(struct timeval));
360
break;
361
}
@@ -370,23 +363,23 @@ void *pluginsd_worker_thread(void *arg)
363
else {
364
error("PLUGINSD: '%s' is sending command '%s' which is not known by netdata. Disabling it.", cd->fullfilename, s);
365
cd->enabled = 0;
373
- // test: killing an exited child kills us - lets check it exists before killing it
374
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
366
+ killpid(cd->pid, SIGTERM);
367
break;
368
}
369
}
370
371
+ info("PLUGINSD: '%s' on pid %d stopped.", cd->fullfilename, cd->pid);
372
+
373
// fgets() failed or loop broke
374
mypclose(fp, cd->pid);
381
- cd->pid = 0;
375
376
if(!count && cd->enabled) {
384
- error("PLUGINSD: '%s' does not generate usefull output. Disabling it.", cd->fullfilename);
385
- cd->enabled = 0;
386
- // test: killing an exited child kills us - lets check it exists before killing it
387
- if(kill(cd->pid, 0) != -1) kill(cd->pid, SIGTERM);
377
+ error("PLUGINSD: '%s' (pid %d) does not generate usefull output. Waiting a bit before starting it again.", cd->fullfilename, cd->pid);
378
+ sleep(cd->update_every * 10);
379
}
380
381
+ cd->pid = 0;
382
+
383
if(cd->enabled) sleep(cd->update_every);
384
else break;
385
}
src/popen.c
+2
@@ -117,6 +117,8 @@ FILE *mypopen(const char *command, pid_t *pidptr)
117
}
118
119
void mypclose(FILE *fp, pid_t pid) {
120
+ debug(D_EXIT, "Request to mypclose() on pid %d", pid);
121
+
122
/*mypopen_del(fp);*/
123
fclose(fp);
124