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:
parent
7f23e0461d
commit
77262c359c
@ -57,6 +57,11 @@
|
|||||||
.Ar daemon
|
.Ar daemon
|
||||||
.Fl r , -chroot
|
.Fl r , -chroot
|
||||||
.Ar chrootpath
|
.Ar chrootpath
|
||||||
|
.Nm
|
||||||
|
.Fl s , -signal
|
||||||
|
.Ar signal
|
||||||
|
.Fl r , -chroot
|
||||||
|
.Ar chrootpath
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
provides a consistent method of starting, stopping and restarting
|
provides a consistent method of starting, stopping and restarting
|
||||||
@ -64,11 +69,8 @@ daemons. If
|
|||||||
.Fl K , -stop
|
.Fl K , -stop
|
||||||
is not provided, then we assume we are starting the daemon.
|
is not provided, then we assume we are starting the daemon.
|
||||||
.Nm
|
.Nm
|
||||||
only works with daemons which do not fork. Also, it uses its own pid
|
only works with daemons which do not fork. If your daemon has options to
|
||||||
file, so the daemon should not write a pid file, or the pid file passed
|
tell it not to fork, it should be configured to not fork.
|
||||||
to
|
|
||||||
.Nm
|
|
||||||
should not be the one the daemon writes.
|
|
||||||
.Pp
|
.Pp
|
||||||
Here are the options to specify the daemon and how it should start or stop:
|
Here are the options to specify the daemon and how it should start or stop:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
|
@ -68,7 +68,7 @@ static struct pam_conv conv = { NULL, NULL};
|
|||||||
|
|
||||||
const char *applet = NULL;
|
const char *applet = NULL;
|
||||||
const char *extraopts = 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;
|
getoptstring_COMMON;
|
||||||
const struct option longopts[] = {
|
const struct option longopts[] = {
|
||||||
{ "healthcheck-timer", 1, NULL, 'a'},
|
{ "healthcheck-timer", 1, NULL, 'a'},
|
||||||
@ -86,6 +86,7 @@ const struct option longopts[] = {
|
|||||||
{ "respawn-period", 1, NULL, 'P'},
|
{ "respawn-period", 1, NULL, 'P'},
|
||||||
{ "retry", 1, NULL, 'R'},
|
{ "retry", 1, NULL, 'R'},
|
||||||
{ "chroot", 1, NULL, 'r'},
|
{ "chroot", 1, NULL, 'r'},
|
||||||
|
{ "signal", 1, NULL, 's'},
|
||||||
{ "start", 0, NULL, 'S'},
|
{ "start", 0, NULL, 'S'},
|
||||||
{ "user", 1, NULL, 'u'},
|
{ "user", 1, NULL, 'u'},
|
||||||
{ "stdout", 1, NULL, '1'},
|
{ "stdout", 1, NULL, '1'},
|
||||||
@ -109,6 +110,7 @@ const char * const longopts_help[] = {
|
|||||||
"Set respawn time period",
|
"Set respawn time period",
|
||||||
"Retry schedule to use when stopping",
|
"Retry schedule to use when stopping",
|
||||||
"Chroot to this directory",
|
"Chroot to this directory",
|
||||||
|
"Send a signal to the daemon",
|
||||||
"Start daemon",
|
"Start daemon",
|
||||||
"Change the process user",
|
"Change the process user",
|
||||||
"Redirect stdout to file",
|
"Redirect stdout to file",
|
||||||
@ -142,6 +144,8 @@ static int respawn_count = 0;
|
|||||||
static int respawn_delay = 0;
|
static int respawn_delay = 0;
|
||||||
static int respawn_max = 10;
|
static int respawn_max = 10;
|
||||||
static int respawn_period = 5;
|
static int respawn_period = 5;
|
||||||
|
static char *fifopath = NULL;
|
||||||
|
static int fifo_fd = 0;
|
||||||
static char *pidfile = NULL;
|
static char *pidfile = NULL;
|
||||||
static char *svcname = NULL;
|
static char *svcname = NULL;
|
||||||
|
|
||||||
@ -439,10 +443,14 @@ static void child_process(char *exec, char **argv)
|
|||||||
static void supervisor(char *exec, char **argv)
|
static void supervisor(char *exec, char **argv)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
char buf[2048];
|
||||||
|
char cmd[2048];
|
||||||
|
int count;
|
||||||
int health_status;
|
int health_status;
|
||||||
int healthcheck_respawn;
|
int healthcheck_respawn;
|
||||||
int i;
|
int i;
|
||||||
int nkilled;
|
int nkilled;
|
||||||
|
int sig_send;
|
||||||
pid_t health_pid;
|
pid_t health_pid;
|
||||||
pid_t wait_pid;
|
pid_t wait_pid;
|
||||||
sigset_t old_signals;
|
sigset_t old_signals;
|
||||||
@ -489,9 +497,29 @@ static void supervisor(char *exec, char **argv)
|
|||||||
alarm(healthcheckdelay);
|
alarm(healthcheckdelay);
|
||||||
else if (healthchecktimer)
|
else if (healthchecktimer)
|
||||||
alarm(healthchecktimer);
|
alarm(healthchecktimer);
|
||||||
|
fifo_fd = open(fifopath, O_RDONLY |O_NONBLOCK);
|
||||||
while (!exiting) {
|
while (!exiting) {
|
||||||
healthcheck_respawn = 0;
|
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) {
|
if (do_healthcheck) {
|
||||||
do_healthcheck = 0;
|
do_healthcheck = 0;
|
||||||
alarm(0);
|
alarm(0);
|
||||||
@ -578,6 +606,8 @@ static void supervisor(char *exec, char **argv)
|
|||||||
|
|
||||||
if (pidfile && exists(pidfile))
|
if (pidfile && exists(pidfile))
|
||||||
unlink(pidfile);
|
unlink(pidfile);
|
||||||
|
if (fifopath && exists(fifopath))
|
||||||
|
unlink(fifopath);
|
||||||
if (svcname) {
|
if (svcname) {
|
||||||
rc_service_daemon_set(svcname, exec, (const char *const *)argv,
|
rc_service_daemon_set(svcname, exec, (const char *const *)argv,
|
||||||
pidfile, false);
|
pidfile, false);
|
||||||
@ -595,6 +625,7 @@ int main(int argc, char **argv)
|
|||||||
bool start = false;
|
bool start = false;
|
||||||
bool stop = false;
|
bool stop = false;
|
||||||
bool reexec = false;
|
bool reexec = false;
|
||||||
|
bool sendsig = false;
|
||||||
char *exec = NULL;
|
char *exec = NULL;
|
||||||
char *retry = NULL;
|
char *retry = NULL;
|
||||||
int sig = SIGTERM;
|
int sig = SIGTERM;
|
||||||
@ -700,6 +731,10 @@ int main(int argc, char **argv)
|
|||||||
eerrorx("Invalid respawn-period value '%s'", optarg);
|
eerrorx("Invalid respawn-period value '%s'", optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's': /* --signal */
|
||||||
|
sig = parse_signal(applet, optarg);
|
||||||
|
sendsig = true;
|
||||||
|
break;
|
||||||
case 'S': /* --start */
|
case 'S': /* --start */
|
||||||
start = true;
|
start = true;
|
||||||
break;
|
break;
|
||||||
@ -818,6 +853,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
umask(numask);
|
umask(numask);
|
||||||
xasprintf(&pidfile, "/var/run/supervise-%s.pid", svcname);
|
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) {
|
if (reexec) {
|
||||||
str = rc_service_value_get(svcname, "argc");
|
str = rc_service_value_get(svcname, "argc");
|
||||||
@ -989,5 +1028,18 @@ int main(int argc, char **argv)
|
|||||||
rc_service_mark(svcname, RC_SERVICE_STOPPED);
|
rc_service_mark(svcname, RC_SERVICE_STOPPED);
|
||||||
}
|
}
|
||||||
exit(EXIT_SUCCESS);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user