diff options
author | pjd <pjd@FreeBSD.org> | 2010-09-22 19:08:11 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2010-09-22 19:08:11 +0000 |
commit | 67279d16ee319cb5904e06282acb094216407755 (patch) | |
tree | bacc321cf8b67b3b710a5e41960ab926cee818ab /sbin | |
parent | 2eee4ca70d37cd47c54a9641d8bd574f33579200 (diff) | |
download | FreeBSD-src-67279d16ee319cb5904e06282acb094216407755.zip FreeBSD-src-67279d16ee319cb5904e06282acb094216407755.tar.gz |
Switch to sigprocmask(2) API also in the main process and secondary process.
This way the primary process inherits signal mask from the main process,
which fixes a race where signal is delivered to the primary process before
configuring signal mask.
Reported by: Mikolaj Golub <to.my.trociny@gmail.com>
MFC after: 3 days
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/hastd/hastd.c | 84 | ||||
-rw-r--r-- | sbin/hastd/hastd.h | 2 | ||||
-rw-r--r-- | sbin/hastd/primary.c | 13 | ||||
-rw-r--r-- | sbin/hastd/secondary.c | 6 |
4 files changed, 44 insertions, 61 deletions
diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c index 651730d..e47b19d 100644 --- a/sbin/hastd/hastd.c +++ b/sbin/hastd/hastd.c @@ -63,10 +63,6 @@ __FBSDID("$FreeBSD$"); const char *cfgpath = HAST_CONFIG; /* Hastd configuration. */ static struct hastd_config *cfg; -/* Was SIGCHLD signal received? */ -bool sigchld_received = false; -/* Was SIGHUP signal received? */ -bool sighup_received = false; /* Was SIGINT or SIGTERM signal received? */ bool sigexit_received = false; /* PID file handle. */ @@ -83,26 +79,6 @@ usage(void) } static void -sighandler(int sig) -{ - - switch (sig) { - case SIGINT: - case SIGTERM: - sigexit_received = true; - break; - case SIGCHLD: - sigchld_received = true; - break; - case SIGHUP: - sighup_received = true; - break; - default: - assert(!"invalid condition"); - } -} - -static void g_gate_load(void) { @@ -625,26 +601,41 @@ static void main_loop(void) { struct hast_resource *res; - struct timeval timeout; - int fd, maxfd, ret; + struct timeval seltimeout; + struct timespec sigtimeout; + int fd, maxfd, ret, signo; + sigset_t mask; fd_set rfds; - timeout.tv_sec = REPORT_INTERVAL; - timeout.tv_usec = 0; + seltimeout.tv_sec = REPORT_INTERVAL; + seltimeout.tv_usec = 0; + sigtimeout.tv_sec = 0; + sigtimeout.tv_nsec = 0; + + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); for (;;) { - if (sigexit_received) { - sigexit_received = false; - terminate_workers(); - exit(EX_OK); - } - if (sigchld_received) { - sigchld_received = false; - child_exit(); - } - if (sighup_received) { - sighup_received = false; - hastd_reload(); + while ((signo = sigtimedwait(&mask, NULL, &sigtimeout)) != -1) { + switch (signo) { + case SIGINT: + case SIGTERM: + sigexit_received = true; + terminate_workers(); + exit(EX_OK); + break; + case SIGCHLD: + child_exit(); + break; + case SIGHUP: + hastd_reload(); + break; + default: + assert(!"invalid condition"); + } } /* Setup descriptors for select(2). */ @@ -666,7 +657,7 @@ main_loop(void) } assert(maxfd + 1 <= (int)FD_SETSIZE); - ret = select(maxfd + 1, &rfds, NULL, NULL, &timeout); + ret = select(maxfd + 1, &rfds, NULL, NULL, &seltimeout); if (ret == 0) hook_check(false); else if (ret == -1) { @@ -701,6 +692,7 @@ main(int argc, char *argv[]) pid_t otherpid; bool foreground; int debuglevel; + sigset_t mask; g_gate_load(); @@ -751,10 +743,12 @@ main(int argc, char *argv[]) cfg = yy_config_parse(cfgpath, true); assert(cfg != NULL); - signal(SIGINT, sighandler); - signal(SIGTERM, sighandler); - signal(SIGHUP, sighandler); - signal(SIGCHLD, sighandler); + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); + PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); + PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); /* Listen on control address. */ if (proto_server(cfg->hc_controladdr, &cfg->hc_controlconn) < 0) { diff --git a/sbin/hastd/hastd.h b/sbin/hastd/hastd.h index a32e512..0186e81 100644 --- a/sbin/hastd/hastd.h +++ b/sbin/hastd/hastd.h @@ -40,7 +40,7 @@ #include "hast.h" extern const char *cfgpath; -extern bool sigchld_received, sigexit_received, sighup_received; +extern bool sigexit_received; extern struct pidfh *pfh; void hastd_primary(struct hast_resource *res); diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c index 5d6896e..d99bfd7 100644 --- a/sbin/hastd/primary.c +++ b/sbin/hastd/primary.c @@ -313,7 +313,6 @@ init_environment(struct hast_resource *res __unused) { struct hio *hio; unsigned int ii, ncomps; - sigset_t mask; /* * In the future it might be per-resource value. @@ -420,15 +419,6 @@ init_environment(struct hast_resource *res __unused) hio->hio_ggio.gctl_error = 0; TAILQ_INSERT_HEAD(&hio_free_list, hio, hio_free_next); } - - /* - * Turn on signals handling. - */ - PJDLOG_VERIFY(sigemptyset(&mask) == 0); - PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); - PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); - PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); - PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); } static void @@ -800,9 +790,6 @@ hastd_primary(struct hast_resource *res) setproctitle("%s (primary)", res->hr_name); - signal(SIGHUP, SIG_DFL); - signal(SIGCHLD, SIG_DFL); - /* Declare that we are sender. */ proto_send(res->hr_event, NULL, 0); diff --git a/sbin/hastd/secondary.c b/sbin/hastd/secondary.c index 9e1e537..403c5b2 100644 --- a/sbin/hastd/secondary.c +++ b/sbin/hastd/secondary.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <fcntl.h> #include <libgeom.h> #include <pthread.h> +#include <signal.h> #include <stdint.h> #include <stdio.h> #include <string.h> @@ -334,6 +335,7 @@ init_remote(struct hast_resource *res, struct nv *nvin) void hastd_secondary(struct hast_resource *res, struct nv *nvin) { + sigset_t mask; pthread_t td; pid_t pid; int error; @@ -380,8 +382,8 @@ hastd_secondary(struct hast_resource *res, struct nv *nvin) setproctitle("%s (secondary)", res->hr_name); - signal(SIGHUP, SIG_DFL); - signal(SIGCHLD, SIG_DFL); + PJDLOG_VERIFY(sigemptyset(&mask) == 0); + PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); /* Declare that we are sender. */ proto_send(res->hr_event, NULL, 0); |