diff options
-rwxr-xr-x | netdata-installer.sh | 1 | ||||
-rw-r--r-- | src/daemon.c | 49 | ||||
-rw-r--r-- | src/main.c | 93 | ||||
-rw-r--r-- | src/main.h | 4 | ||||
-rw-r--r-- | src/popen.c | 20 | ||||
-rw-r--r-- | system/netdata.service.in | 3 |
6 files changed, 77 insertions, 93 deletions
diff --git a/netdata-installer.sh b/netdata-installer.sh index 3154247306..d8c073ae57 100755 --- a/netdata-installer.sh +++ b/netdata-installer.sh @@ -11,6 +11,7 @@ then fi LC_ALL=C +umask 022 # you can set CFLAGS before running installer CFLAGS="${CFLAGS--O3}" diff --git a/src/daemon.c b/src/daemon.c index 33af252da0..2a56ae0cce 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -30,49 +30,8 @@ int pidfd = -1; void sig_handler(int signo) { - switch(signo) { - case SIGILL: - case SIGABRT: - case SIGFPE: - case SIGSEGV: - case SIGBUS: - case SIGSYS: - case SIGTRAP: - case SIGXCPU: - case SIGXFSZ: - infoerr("Death signaled exit (signal %d).", signo); - signal(signo, SIG_DFL); - break; - - case SIGKILL: - case SIGTERM: - case SIGQUIT: - case SIGINT: - case SIGHUP: - case SIGUSR1: - case SIGUSR2: - infoerr("Signaled exit (signal %d).", signo); - signal(SIGPIPE, SIG_IGN); - signal(SIGTERM, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGHUP, SIG_IGN); - signal(SIGINT, SIG_IGN); - signal(SIGCHLD, SIG_IGN); - netdata_cleanup_and_exit(1); - break; - - case SIGPIPE: - infoerr("Signaled PIPE (signal %d).", signo); - // this is received when web clients send a reset - // no need to log it. - // infoerr("Ignoring signal %d.", signo); - break; - - default: - info("Signal %d received. Falling back to default action for it.", signo); - signal(signo, SIG_DFL); - break; - } + if(signo) + netdata_exit = 1; } int become_user(const char *username) @@ -249,10 +208,6 @@ int become_daemon(int dont_fork, int close_all_files, const char *user, const ch } } - signal(SIGCHLD, SIG_IGN); - signal(SIGHUP, SIG_IGN); - signal(SIGWINCH, SIG_IGN); - // fork() again if(!dont_fork) { int i = fork(); diff --git a/src/main.c b/src/main.c index 642638bf54..50c733d32f 100644 --- a/src/main.c +++ b/src/main.c @@ -40,7 +40,7 @@ extern void *cgroups_main(void *ptr); -int netdata_exit = 0; +volatile sig_atomic_t netdata_exit = 0; void netdata_cleanup_and_exit(int ret) { @@ -123,19 +123,7 @@ int killpid(pid_t pid, int sig) } 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: @@ -412,6 +400,41 @@ int main(int argc, char **argv) // -------------------------------------------------------------------- + // block signals while initializing threads. + // this causes the threads to block signals. + sigset_t sigset; + sigfillset(&sigset); + + if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1) { + error("Could not block signals for threads"); + } + + // Catch signals which we want to use to quit savely + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGHUP); + sigaddset(&sa.sa_mask, SIGINT); + sigaddset(&sa.sa_mask, SIGTERM); + sa.sa_handler = sig_handler; + if(sigaction(SIGHUP, &sa, NULL) == -1) { + error("Failed to change signal handler for SIGHUP"); + } + if(sigaction(SIGINT, &sa, NULL) == -1) { + error("Failed to change signal handler for SIGINT"); + } + if(sigaction(SIGTERM, &sa, NULL) == -1) { + error("Failed to change signal handler for SIGTERM"); + } + // Ignore SIGPIPE completely. + // INFO: If we add signals here we have to unblock them + // at popen.c when running a external plugin. + sa.sa_handler = SIG_IGN; + if(sigaction(SIGPIPE, &sa, NULL) == -1) { + error("Failed to change signal handler for SIGTERM"); + } + + // -------------------------------------------------------------------- + i = pthread_attr_init(&attr); if(i != 0) fatal("pthread_attr_init() failed with code %d.", i); @@ -492,24 +515,6 @@ int main(int argc, char **argv) info("NetData started on pid %d", getpid()); - // catch all signals - for (i = 1 ; i < 65 ;i++) { - switch(i) { - case SIGKILL: // not catchable - case SIGSTOP: // not catchable - break; - - case SIGSEGV: - case SIGFPE: - case SIGCHLD: - signal(i, SIG_DFL); - break; - - default: - signal(i, sig_handler); - break; - } - } // ------------------------------------------------------------------------ // get default pthread stack size @@ -550,18 +555,22 @@ int main(int argc, char **argv) else info("Not starting thread %s.", st->name); } - // for future use - the main thread - while(1) { - if(netdata_exit != 0) { - netdata_exit++; + // ------------------------------------------------------------------------ + // block signals while initializing threads. + sigset_t sigset; + sigfillset(&sigset); - if(netdata_exit > 5) { - netdata_cleanup_and_exit(0); - exit(0); - } - } - sleep(2); + if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) { + error("Could not unblock signals for threads"); } - exit(0); + // Handle flags set in the signal handler. + while(1) { + pause(); + if(netdata_exit) { + info("Exit main loop of netdata."); + netdata_cleanup_and_exit(0); + exit(0); + } + } } diff --git a/src/main.h b/src/main.h index 6a90efd9d4..d9edda58e6 100644 --- a/src/main.h +++ b/src/main.h @@ -1,7 +1,9 @@ #ifndef NETDATA_MAIN_H #define NETDATA_MAIN_H 1 -extern int netdata_exit; +#include <signal.h> + +extern volatile sig_atomic_t netdata_exit; extern void kill_childs(void); extern int killpid(pid_t pid, int signal); diff --git a/src/popen.c b/src/popen.c index 882a4cc5a6..d4e86607bc 100644 --- a/src/popen.c +++ b/src/popen.c @@ -114,10 +114,26 @@ FILE *mypopen(const char *command, pid_t *pidptr) #endif // reset all signals - for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i, SIG_DFL); + { + sigset_t sigset; + sigfillset(&sigset); + + if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) { + error("Could not block signals for threads"); + } + // We only need to reset ignored signals. + // Signals with signal handlers are reset by default. + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + if(sigaction(SIGPIPE, &sa, NULL) == -1) { + error("Failed to change signal handler for SIGTERM"); + } + } + info("executing command: '%s' on pid %d.", command, getpid()); - execl("/bin/sh", "sh", "-c", command, NULL); + execl("/bin/sh", "sh", "-c", command, NULL); exit(1); } diff --git a/system/netdata.service.in b/system/netdata.service.in index bc26cc9dcc..91db6122d8 100644 --- a/system/netdata.service.in +++ b/system/netdata.service.in @@ -9,7 +9,8 @@ User=root Group=root PIDFile=@localstatedir_POST@/run/netdata.pid ExecStart=@sbindir_POST@/netdata -pidfile @localstatedir_POST@/run/netdata.pid -ExecStop=/bin/kill -SIGTERM $MAINPID +KillMode=mixed +KillSignal=SIGTERM TimeoutStopSec=30 [Install] |