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
This commit is contained in:
Pawel Jakub Dawidek 2010-09-22 19:08:11 +00:00
parent 196abd3518
commit 9dd5a6cb0f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=213009
4 changed files with 44 additions and 61 deletions

View File

@ -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. */
@ -82,26 +78,6 @@ usage(void)
errx(EX_USAGE, "[-dFh] [-c config] [-P pidfile]");
}
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) {

View File

@ -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);

View File

@ -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);

View File

@ -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);