signal(SIGQUIT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
+ signal(SIGCHLD, SIG_IGN);
kill_childs();
- process_childs(0);
rrdset_free_all();
//unlink("/var/run/netdata.pid");
info("NetData exiting. Bye bye...");
// info("Ignoring signal %d. Errno: %d (%s)", signo, errno, strerror(errno));
break;
-
- case SIGCHLD:
- info("Received SIGCHLD (signal %d).", signo);
- process_childs(0);
- break;
-
default:
info("Signal %d received. Falling back to default action for it.", signo);
signal(signo, SIG_DFL);
if (setsid() < 0)
exit(2);
- signal(SIGCHLD, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
signal(SIGWINCH, SIG_IGN);
// fork() again
// catch all signals
- for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV && i != SIGFPE) signal(i, sig_handler);
-
+ for (i = 1 ; i < 65 ;i++) {
+ switch(i) {
+ case SIGSEGV:
+ case SIGFPE:
+ case SIGCHLD:
+ signal(i, SIG_DFL);
+ break;
+
+ default:
+ signal(i, sig_handler);
+ break;
+ }
+ }
+
for (i = 0; static_threads[i].name != NULL ; i++) {
struct netdata_static_thread *st = &static_threads[i];
else info("Not starting thread %s.", st->name);
}
- // the main process - the web server listener
- // this never ends
- // socket_listen_main(NULL);
- while(1) {
- process_childs(1);
- sleep(1);
- }
+ // for future use - the main thread
+ while(1) sleep(60);
exit(0);
}
// debug(D_TC_LOOP, "IGNORED line");
//}
}
- mypclose(fp);
+ mypclose(fp, tc_child_pid);
+ tc_child_pid = 0;
if(device) {
// tc_device_free(device);
}
// fgets() failed or loop broke
- mypclose(fp);
+ mypclose(fp, cd->pid);
+ cd->pid = 0;
if(!count && cd->enabled) {
error("PLUGINSD: '%s' does not generate usefull output. Disabling it.", cd->fullfilename);
#include "log.h"
#include "popen.h"
+/*
+struct mypopen {
+ pid_t pid;
+ FILE *fp;
+ struct mypopen *next;
+ struct mypopen *prev;
+};
+
+static struct mypopen *mypopen_root = NULL;
+
+static void mypopen_add(FILE *fp, pid_t *pid) {
+ struct mypopen *mp = malloc(sizeof(struct mypopen));
+ if(!mp) {
+ fatal("Cannot allocate %zu bytes", sizeof(struct mypopen))
+ return;
+ }
+
+ mp->fp = fp;
+ mp->pid = pid;
+ mp->next = popen_root;
+ mp->prev = NULL;
+ if(mypopen_root) mypopen_root->prev = mp;
+ mypopen_root = mp;
+}
+
+static void mypopen_del(FILE *fp) {
+ struct mypopen *mp;
+ for(mp = mypopen_root; mp; mp = mp->next)
+ if(mp->fd == fp) break;
+
+ if(!mp) error("Cannot find mypopen() file pointer in open childs.");
+ else {
+ if(mp->next) mp->next->prev = mp->prev;
+ if(mp->prev) mp->prev->next = mp->next;
+ if(mypopen_root == mp) mypopen_root = mp->next;
+ free(mp);
+ }
+}
+*/
#define PIPE_READ 0
#define PIPE_WRITE 1
*pidptr = pid;
close(pipefd[PIPE_WRITE]);
FILE *fp = fdopen(pipefd[PIPE_READ], "r");
+ /*mypopen_add(fp, pid);*/
return(fp);
}
// the child
fflush(NULL);
#endif
- // ignore all signals
+ // reset all signals
for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i, SIG_DFL);
fprintf(stderr, "executing command: '%s' on pid %d.\n", command, getpid());
exit(1);
}
-void mypclose(FILE *fp)
-{
- // this is a very poor implementation of pclose()
- // the caller should catch SIGCHLD and waitpid() on the exited child
- // otherwise the child will be a zombie forever
-
+void mypclose(FILE *fp, pid_t pid) {
+ /*mypopen_del(fp);*/
fclose(fp);
-}
-void process_childs(int wait)
-{
siginfo_t info;
- int options = WEXITED;
- if(!wait) options |= WNOHANG;
-
- info.si_pid = 0;
- while(waitid(P_ALL, 0, &info, options) == 0) {
- if(!info.si_pid) break;
+ if(waitid(P_PID, pid, &info, WEXITED) != -1) {
switch(info.si_code) {
case CLD_EXITED:
error("pid %d exited with code %d.", info.si_pid, info.si_status);
error("pid %d gave us a SIGCHLD with code %d and status %d.", info.si_pid, info.si_code, info.si_status);
break;
}
-
- // prevent an infinite loop
- info.si_pid = 0;
}
+ else error("Cannot waitid() for pid %d", pid);
}
#define PIPE_WRITE 1
extern FILE *mypopen(const char *command, pid_t *pidptr);
-extern void mypclose(FILE *fp);
-extern void process_childs(int wait);
+extern void mypclose(FILE *fp, pid_t pid);
#endif /* NETDATA_POPEN_H */
var MINIMUM_THUMB_GRAPH_WIDTH = 400; // thumb chart will generally try to be wider than that
var TARGET_THUMB_GRAPH_HEIGHT = 180; // the height of the thumb charts
-var THUMBS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?
-var THUMBS_POINTS_DIVISOR = 4;
-var THUMBS_STACKED_POINTS_DIVISOR = 10;
+var THUMBS_MAX_TIME_TO_SHOW = 240; // how much time the thumb charts will present?
+var THUMBS_POINTS_DIVISOR = 3;
+var THUMBS_STACKED_POINTS_DIVISOR = 3;
-var GROUPS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?
-var GROUPS_POINTS_DIVISOR = 4;
-var GROUPS_STACKED_POINTS_DIVISOR = 10;
+var GROUPS_MAX_TIME_TO_SHOW = 120; // how much time the thumb charts will present?
+var GROUPS_POINTS_DIVISOR = 2;
+var GROUPS_STACKED_POINTS_DIVISOR = 2;
var MAINCHART_MAX_TIME_TO_SHOW = 600; // how much time the main chart will present by default?
var MAINCHART_POINTS_DIVISOR = 5; // how much detailed will the main chart be by default? 1 = finest, higher is faster