supervise-daemon: add support for a fifo

This will allow us to signal the daemon we are supervising as well as
send other commands to the supervisor in the future.

This fixes #227.
This commit is contained in:
William Hubbs 2018-11-30 11:45:48 -06:00
parent 7f23e0461d
commit 77262c359c
2 changed files with 61 additions and 7 deletions

View File

@ -57,6 +57,11 @@
.Ar daemon
.Fl r , -chroot
.Ar chrootpath
.Nm
.Fl s , -signal
.Ar signal
.Fl r , -chroot
.Ar chrootpath
.Sh DESCRIPTION
.Nm
provides a consistent method of starting, stopping and restarting
@ -64,11 +69,8 @@ daemons. If
.Fl K , -stop
is not provided, then we assume we are starting the daemon.
.Nm
only works with daemons which do not fork. Also, it uses its own pid
file, so the daemon should not write a pid file, or the pid file passed
to
.Nm
should not be the one the daemon writes.
only works with daemons which do not fork. If your daemon has options to
tell it not to fork, it should be configured to not fork.
.Pp
Here are the options to specify the daemon and how it should start or stop:
.Bl -tag -width indent

View File

@ -68,7 +68,7 @@ static struct pam_conv conv = { NULL, NULL};
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:Su:1:2:3" \
const char *getoptstring = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:s:Su:1:2:3" \
getoptstring_COMMON;
const struct option longopts[] = {
{ "healthcheck-timer", 1, NULL, 'a'},
@ -86,6 +86,7 @@ const struct option longopts[] = {
{ "respawn-period", 1, NULL, 'P'},
{ "retry", 1, NULL, 'R'},
{ "chroot", 1, NULL, 'r'},
{ "signal", 1, NULL, 's'},
{ "start", 0, NULL, 'S'},
{ "user", 1, NULL, 'u'},
{ "stdout", 1, NULL, '1'},
@ -109,6 +110,7 @@ const char * const longopts_help[] = {
"Set respawn time period",
"Retry schedule to use when stopping",
"Chroot to this directory",
"Send a signal to the daemon",
"Start daemon",
"Change the process user",
"Redirect stdout to file",
@ -142,6 +144,8 @@ static int respawn_count = 0;
static int respawn_delay = 0;
static int respawn_max = 10;
static int respawn_period = 5;
static char *fifopath = NULL;
static int fifo_fd = 0;
static char *pidfile = NULL;
static char *svcname = NULL;
@ -439,10 +443,14 @@ static void child_process(char *exec, char **argv)
static void supervisor(char *exec, char **argv)
{
FILE *fp;
char buf[2048];
char cmd[2048];
int count;
int health_status;
int healthcheck_respawn;
int i;
int nkilled;
int sig_send;
pid_t health_pid;
pid_t wait_pid;
sigset_t old_signals;
@ -489,9 +497,29 @@ static void supervisor(char *exec, char **argv)
alarm(healthcheckdelay);
else if (healthchecktimer)
alarm(healthchecktimer);
fifo_fd = open(fifopath, O_RDONLY |O_NONBLOCK);
while (!exiting) {
healthcheck_respawn = 0;
wait_pid = waitpid(child_pid, &i, 0);
wait_pid = waitpid(child_pid, &i, WNOHANG);
memset(buf, 0, sizeof(buf));
if (fifo_fd >= 0) {
count = read(fifo_fd, buf, sizeof(buf) - 1);
if (count != -1)
buf[count] = 0;
}
if (strlen(buf) > 0) {
syslog(LOG_DEBUG, "Received %s from fifo", buf);
if (strncasecmp(buf, "sig", 3) == 0) {
if ((sscanf(buf, "%s %d", cmd, &sig_send) == 2)
&& (sig_send >= 0 && sig_send < NSIG)) {
syslog(LOG_INFO, "Sending signal %d to %d", sig_send,
child_pid);
if (kill(child_pid, sig_send) == -1)
syslog(LOG_ERR, "Unable to send signal %d to %d",
sig_send, child_pid);
}
}
}
if (do_healthcheck) {
do_healthcheck = 0;
alarm(0);
@ -578,6 +606,8 @@ static void supervisor(char *exec, char **argv)
if (pidfile && exists(pidfile))
unlink(pidfile);
if (fifopath && exists(fifopath))
unlink(fifopath);
if (svcname) {
rc_service_daemon_set(svcname, exec, (const char *const *)argv,
pidfile, false);
@ -595,6 +625,7 @@ int main(int argc, char **argv)
bool start = false;
bool stop = false;
bool reexec = false;
bool sendsig = false;
char *exec = NULL;
char *retry = NULL;
int sig = SIGTERM;
@ -700,6 +731,10 @@ int main(int argc, char **argv)
eerrorx("Invalid respawn-period value '%s'", optarg);
break;
case 's': /* --signal */
sig = parse_signal(applet, optarg);
sendsig = true;
break;
case 'S': /* --start */
start = true;
break;
@ -818,6 +853,10 @@ int main(int argc, char **argv)
umask(numask);
xasprintf(&pidfile, "/var/run/supervise-%s.pid", svcname);
xasprintf(&fifopath, "%s/supervise-%s.ctl", RC_SVCDIR, svcname);
if (mkfifo(fifopath, 0600) == -1 && errno != EEXIST)
eerrorx("%s: unable to create control fifo: %s",
applet, strerror(errno));
if (reexec) {
str = rc_service_value_get(svcname, "argc");
@ -989,5 +1028,18 @@ int main(int argc, char **argv)
rc_service_mark(svcname, RC_SERVICE_STOPPED);
}
exit(EXIT_SUCCESS);
} else if (sendsig) {
fifo_fd = open(fifopath, O_WRONLY |O_NONBLOCK);
if (fifo_fd < 0)
eerrorx("%s: unable to open control fifo %s", applet, strerror(errno));
xasprintf(&str, "sig %d", sig);
x = write(fifo_fd, str, strlen(str));
if (x == -1) {
free(tmp);
eerrorx("%s: error writing to control fifo: %s", applet,
strerror(errno));
}
free(tmp);
exit(EXIT_SUCCESS);
}
}