From: Christian Pointner Date: Sun, 3 May 2009 13:41:04 +0000 (+0000) Subject: added signal handling without races X-Git-Url: https://git.realraum.at/?p=svn42.git;a=commitdiff_plain;h=bd2c78928d653160ef85e25e03e8b4e721635ac6 added signal handling without races --- diff --git a/door_daemon/door_daemon.c b/door_daemon/door_daemon.c index 6e4db12..cf12668 100644 --- a/door_daemon/door_daemon.c +++ b/door_daemon/door_daemon.c @@ -238,7 +238,12 @@ int main_loop(int door_fd, int cmd_listen_fd) int max_fd = door_fd > cmd_listen_fd ? door_fd : cmd_listen_fd; cmd_t* cmd_q = NULL; - signal_init(); + int sig_fd = signal_init(); + if(sig_fd < 0) + return -1; + FD_SET(sig_fd, &readfds); + max_fd = (max_fd < sig_fd) ? sig_fd : max_fd; + int return_value = 0; while(!return_value) { memcpy(&tmpfds, &readfds, sizeof(tmpfds)); @@ -249,13 +254,14 @@ int main_loop(int door_fd, int cmd_listen_fd) return_value = -1; break; } - if(!ret) + if(!ret || ret == -1) continue; - if(signal_exit) { + if(signal_handle()) { return_value = 1; break; } + FD_CLR(sig_fd, &tmpfds); if(FD_ISSET(door_fd, &tmpfds)) { return_value = process_door(door_fd, &cmd_q); @@ -298,6 +304,7 @@ int main_loop(int door_fd, int cmd_listen_fd) } cmd_clear(&cmd_q); + signal_stop(); return return_value; } diff --git a/door_daemon/sig_handler.c b/door_daemon/sig_handler.c index 6fd4b85..7a1ad74 100644 --- a/door_daemon/sig_handler.c +++ b/door_daemon/sig_handler.c @@ -36,29 +36,123 @@ #include "log.h" #include +#include +#include +#include +#include + #include "sig_handler.h" -volatile sig_atomic_t signal_exit = 0; +#include + + +static int sig_pipe_fds[2]; + -void signal_init() +static void sig_handler(int sig) { - signal(SIGINT, handle_signal); - signal(SIGQUIT, handle_signal); - signal(SIGTERM, handle_signal); - signal(SIGHUP, handle_signal); - signal(SIGUSR1, handle_signal); - signal(SIGUSR2, handle_signal); + sigset_t set; + int ret = read(sig_pipe_fds[0], &set, sizeof(sigset_t)); + if(ret != sizeof(sigset_t)) + sigemptyset(&set); + + sigaddset(&set, sig); + ret = write(sig_pipe_fds[1], &set, sizeof(sigset_t)); +} + + +int signal_init() +{ + if(pipe(sig_pipe_fds)) { + log_printf(ERROR, "signal handling init failed (pipe error: %s)", strerror(errno)); + return -1; + } + + int i; + for(i=0; i<2; ++i) { + int fd_flags = fcntl(sig_pipe_fds[i], F_GETFL); + if(fd_flags == -1) { + log_printf(ERROR, "signal handling init failed (pipe fd[%d] read flags error: %s)", i, strerror(errno)); + return -1; + } + if(fcntl(sig_pipe_fds[i], F_SETFL, fd_flags | O_NONBLOCK) == -1){ + log_printf(ERROR, "signal handling init failed (pipe fd[%d] write flags error: %s)", i, strerror(errno)); + return -1; + } + } + + struct sigaction act; + act.sa_handler = sig_handler; + sigfillset(&act.sa_mask); + act.sa_flags = 0; + + if((sigaction(SIGINT, &act, NULL) < 0) || + (sigaction(SIGQUIT, &act, NULL) < 0) || + (sigaction(SIGTERM, &act, NULL) < 0) || + (sigaction(SIGHUP, &act, NULL) < 0) || + (sigaction(SIGUSR1, &act, NULL) < 0) || + (sigaction(SIGUSR2, &act, NULL) < 0)) { + + log_printf(ERROR, "signal handling init failed (sigaction error: %s)", strerror(errno)); + close(sig_pipe_fds[0]); + close(sig_pipe_fds[1]); + } + + return sig_pipe_fds[0]; } -void handle_signal(int sig) +int signal_handle() { - switch(sig) { - case SIGINT: log_printf(NOTICE, "SIG-Int caught, exitting"); signal_exit = 1; break; - case SIGQUIT: log_printf(NOTICE, "SIG-Quit caught, exitting"); signal_exit = 1; break; - case SIGTERM: log_printf(NOTICE, "SIG-Term caught, exitting"); signal_exit = 1; break; - case SIGHUP: log_printf(NOTICE, "SIG-Hup caught"); break; - case SIGUSR1: log_printf(NOTICE, "SIG-Usr1 caught"); break; - case SIGUSR2: log_printf(NOTICE, "SIG-Usr2 caught"); break; - default: log_printf(NOTICE, "Signal %d caught, ignoring", sig); break; + sigset_t set, oldset, tmpset; + + sigemptyset(&tmpset); + sigaddset(&tmpset, SIGINT); + sigaddset(&tmpset, SIGQUIT); + sigaddset(&tmpset, SIGTERM); + sigaddset(&tmpset, SIGHUP); + sigaddset(&tmpset, SIGUSR1); + sigaddset(&tmpset, SIGUSR2); + sigprocmask(SIG_BLOCK, &tmpset, &oldset); + + int ret = read(sig_pipe_fds[0], &set, sizeof(sigset_t)); + if(ret != sizeof(sigset_t)) + sigemptyset(&set); + + int return_value = 0; + int sig; + for(sig=1; sig < _NSIG; ++sig) { + if(sigismember(&set, sig)) { + switch(sig) { + case SIGINT: log_printf(NOTICE, "SIG-Int caught, exitting"); return_value = 1; break; + case SIGQUIT: log_printf(NOTICE, "SIG-Quit caught, exitting"); return_value = 1; break; + case SIGTERM: log_printf(NOTICE, "SIG-Term caught, exitting"); return_value = 1; break; + case SIGHUP: log_printf(NOTICE, "SIG-Hup caught"); break; + case SIGUSR1: log_printf(NOTICE, "SIG-Usr1 caught"); break; + case SIGUSR2: log_printf(NOTICE, "SIG-Usr2 caught"); break; + default: log_printf(WARNING, "unknown signal %d caught, ignoring", sig); break; + } + sigdelset(&set, sig); + } } + + sigprocmask(SIG_SETMASK, &oldset, NULL); + return return_value; +} + +void signal_stop() +{ + struct sigaction act; + act.sa_handler = SIG_DFL; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + + sigaction(SIGINT, &act, NULL); + sigaction(SIGQUIT, &act, NULL); + sigaction(SIGTERM, &act, NULL); + sigaction(SIGHUP, &act, NULL); + sigaction(SIGUSR1, &act, NULL); + sigaction(SIGUSR2, &act, NULL); + + close(sig_pipe_fds[0]); + close(sig_pipe_fds[1]); } diff --git a/door_daemon/sig_handler.h b/door_daemon/sig_handler.h index a7779be..9fd6386 100644 --- a/door_daemon/sig_handler.h +++ b/door_daemon/sig_handler.h @@ -37,9 +37,8 @@ #include -extern volatile sig_atomic_t signal_exit; - -void signal_init(); -void handle_signal(int sig); +int signal_init(); +int signal_handle(); +void signal_stop(); #endif