aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Hubbs <w.d.hubbs@gmail.com>2018-11-30 11:45:48 -0600
committerWilliam Hubbs <w.d.hubbs@gmail.com>2018-12-02 18:33:25 -0600
commit77262c359c4aaf15ba00b07cd51f3987ce514769 (patch)
tree07696411df3f4b178326a648e33e112c20858e69
parent7f23e0461d6c6d24f5cfa39b9e404a7ec9cfd9c1 (diff)
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.
-rw-r--r--man/supervise-daemon.812
-rw-r--r--src/rc/supervise-daemon.c56
2 files changed, 61 insertions, 7 deletions
diff --git a/man/supervise-daemon.8 b/man/supervise-daemon.8
index 0da1c5ac..1bf19de0 100644
--- a/man/supervise-daemon.8
+++ b/man/supervise-daemon.8
@@ -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
diff --git a/src/rc/supervise-daemon.c b/src/rc/supervise-daemon.c
index cce0f9db..bfbb85f6 100644
--- a/src/rc/supervise-daemon.c
+++ b/src/rc/supervise-daemon.c
@@ -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);
}
}