aboutsummaryrefslogtreecommitdiffstats
path: root/scan.c
diff options
context:
space:
mode:
authorMarius Halden <marius.h@lden.org>2015-11-27 03:25:38 +0100
committerMarius Halden <marius.h@lden.org>2015-11-27 03:25:38 +0100
commitf1c5678d757e4b945ad044042897bd5ee340900f (patch)
treef1a473cbba112cefcac16467b390fe8050ee2bb1 /scan.c
parent78b219eb5869349e9bb01b0abd59b6a944832d90 (diff)
downloadsvcmon-f1c5678d757e4b945ad044042897bd5ee340900f.tar.gz
svcmon-f1c5678d757e4b945ad044042897bd5ee340900f.tar.bz2
svcmon-f1c5678d757e4b945ad044042897bd5ee340900f.tar.xz
Add timout before restart
Diffstat (limited to 'scan.c')
-rw-r--r--scan.c169
1 files changed, 134 insertions, 35 deletions
diff --git a/scan.c b/scan.c
index 02dc5a7..7a5cc62 100644
--- a/scan.c
+++ b/scan.c
@@ -16,11 +16,6 @@
#include <sys/wait.h>
#include <unistd.h>
-/*
- * TODO:
- * - Don't start procs instantly after they die, wait some seconds first.
- */
-
const char supdir[] = "/home/marius/r/svc";
char *super_path[] = { "/home/marius/r/supervise", NULL, NULL };
@@ -31,7 +26,8 @@ struct svc {
TAILQ_ENTRY(svc) entries;
};
-TAILQ_HEAD(svclist, svc) services = TAILQ_HEAD_INITIALIZER(services);
+TAILQ_HEAD(svcrunlist, svc) services = TAILQ_HEAD_INITIALIZER(services);
+TAILQ_HEAD(svcnorunlist, svc) svc_norun = TAILQ_HEAD_INITIALIZER(svc_norun);
struct svc *
find_svc_sup(pid_t p)
@@ -47,10 +43,9 @@ find_svc_sup(pid_t p)
}
struct svc *
-find_svc_dir(const char *dir)
+find_run_svc_dir(const char *dir)
{
struct svc *np;
-
TAILQ_FOREACH(np, &services, entries) {
if (strcmp(np->dir, dir) == 0)
return np;
@@ -59,10 +54,49 @@ find_svc_dir(const char *dir)
return NULL;
}
+struct svc *
+find_norun_svc_dir(const char *dir)
+{
+ struct svc *np;
+ TAILQ_FOREACH(np, &svc_norun, entries) {
+ if (strcmp(np->dir, dir) == 0)
+ return np;
+ }
+
+ return NULL;
+}
+
+struct svc *
+find_svc_dir(const char *dir)
+{
+ struct svc *tmp;
+
+ tmp = find_run_svc_dir(dir);
+ if (tmp != NULL)
+ return tmp;
+
+ tmp = find_norun_svc_dir(dir);
+ return tmp;
+}
+
void
-remove_svc(struct svc *service)
+move_norun(struct svc *service)
{
TAILQ_REMOVE(&services, service, entries);
+ TAILQ_INSERT_TAIL(&svc_norun, service, entries);
+}
+
+void
+move_run(struct svc *service)
+{
+ TAILQ_REMOVE(&svc_norun, service, entries);
+ TAILQ_INSERT_TAIL(&services, service, entries);
+}
+
+void
+remove_svc_norun(struct svc *service)
+{
+ TAILQ_REMOVE(&svc_norun, service, entries);
if (service->supervisor != -1)
fprintf(stderr, "Removed service (%s) with pid (%d) for supervisor\n", service->dir, service->supervisor);
@@ -119,6 +153,23 @@ start_supervisor(struct svc *service)
}
void
+start_dead()
+{
+ struct svc *np, *tmp;
+
+ TAILQ_FOREACH_SAFE(np, &svc_norun, entries, tmp) {
+ if (!direxists(np->dir)) {
+ remove_svc_norun(np);
+ continue;
+ }
+
+ start_supervisor(np);
+
+ move_run(np);
+ }
+}
+
+void
add_missing_svc(const char *name)
{
struct svc *tmp;
@@ -136,9 +187,7 @@ add_missing_svc(const char *name)
tmp->supervisor = -1;
- TAILQ_INSERT_TAIL(&services, tmp, entries);
-
- start_supervisor(tmp);
+ TAILQ_INSERT_TAIL(&svc_norun, tmp, entries);
}
void
@@ -199,10 +248,10 @@ signal_services(int sig)
}
}
-void
+int
try_wait()
{
- int p, s;
+ int p, s, r = 0;
for (;;) {
struct svc *tmp;
@@ -218,17 +267,17 @@ try_wait()
err(1, "waitpid()");
}
+ r = 1;
+
tmp = find_svc_sup(p);
if (tmp == NULL)
continue; /* XXX: Log something here? */
tmp->supervisor = -1;
-
- if (direxists(tmp->dir))
- start_supervisor(tmp);
- else
- remove_svc(tmp);
+ move_norun(tmp);
}
+
+ return r;
}
int
@@ -321,15 +370,49 @@ signal_existing(int dir_fd)
err(1, "fdclosedir()");
}
+void
+setup_signals()
+{
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+
+ act.sa_handler = SIG_IGN;
+ if (sigaction(SIGCHLD, &act, NULL) == -1)
+ err(1, "sigaction()");
+ if (sigaction(SIGHUP, &act, NULL) == -1)
+ err(1, "sigaction()");
+ if (sigaction(SIGINT, &act, NULL) == -1)
+ err(1, "sigaction()");
+ if (sigaction(SIGTERM, &act, NULL) == -1)
+ err(1, "sigaction()");
+}
+
+void
+reset_signals()
+{
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+
+ act.sa_handler = SIG_DFL;
+ if (sigaction(SIGHUP, &act, NULL) == -1)
+ err(1, "sigaction()");
+ if (sigaction(SIGINT, &act, NULL) == -1)
+ err(1, "sigaction()");
+ if (sigaction(SIGTERM, &act, NULL) == -1)
+ err(1, "sigaction()");
+}
+
int
main(int argc, char **argv)
{
int kq, dir_fd, lock_fd;
- struct kevent evt[3];
+ struct kevent evt[6];
pid_t mypid = getpid();
lock_fd = acquire_lock();
+ setup_signals();
+
if (procctl(P_PID, mypid, PROC_REAP_ACQUIRE, NULL) == -1)
err(1, "procctl()");
@@ -337,37 +420,51 @@ main(int argc, char **argv)
if (dir_fd == -1)
err(1, "open()");
- scan_svcdir(dir_fd);
-
kq = kqueue();
if (kq == -1)
err(1, "kqueue()");
- EV_SET(&evt[0], dir_fd, EVFILT_VNODE, EV_ADD | EV_ENABLE, NOTE_WRITE | NOTE_EXTEND, 0, 0);
- EV_SET(&evt[1], SIGCHLD, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 0);
- EV_SET(&evt[2], 1, EVFILT_TIMER, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_SECONDS, 5, 0);
+ EV_SET(&evt[0], dir_fd, EVFILT_VNODE, EV_ADD | EV_ENABLE, NOTE_WRITE | NOTE_EXTEND, 0, 0);
+ EV_SET(&evt[1], SIGHUP, EVFILT_SIGNAL, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
+ EV_SET(&evt[2], SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
+ EV_SET(&evt[3], SIGTERM, EVFILT_SIGNAL, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
+ EV_SET(&evt[4], SIGCHLD, EVFILT_SIGNAL, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
+ EV_SET(&evt[5], 1, EVFILT_TIMER, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_SECONDS, 5, 0);
- if (kevent(kq, evt, 2, NULL, 0, NULL) == -1)
+ if (kevent(kq, evt, 5, NULL, 0, NULL) == -1)
err(1, "kevent()");
+ scan_svcdir(dir_fd);
+ start_dead();
+
for (;;) {
- struct kevent revt[3];
- int e = kevent(kq, NULL, 0, revt, 3, NULL);
+ struct kevent revt[6];
+ int e = kevent(kq, NULL, 0, revt, 6, NULL);
if (e == -1) {
if (errno != EINTR)
err(1, "kevent()");
} else if (e > 0) {
int i;
- for (i = 0; i < e; e++) {
+ for (i = 0; i < e; i++) {
if (revt[i].filter == EVFILT_VNODE && revt[i].ident == dir_fd) {
scan_svcdir(dir_fd);
- } else if (revt[i].filter == EVFILT_SIGNAL && revt[i].ident == SIGCHLD) {
- if (revt[i].ident == SIGCHLD)
- try_wait();
- else if (revt[i].ident == SIGHUP || revt[i].ident == SIGINT || revt[i].ident == SIGTERM)
+ } else if (revt[i].filter == EVFILT_SIGNAL) {
+ if (revt[i].ident == SIGCHLD) {
+ if (try_wait()) {
+ if (kevent(kq, &evt[5], 1, NULL, 0, NULL) == -1)
+ err(1, "kevent()");
+ }
+ }
+ if (revt[i].ident == SIGHUP || revt[i].ident == SIGINT || revt[i].ident == SIGTERM) {
+ fprintf(stderr, "Quit\n");
goto end;
- } else if (revt[i].filter == EVFILT_TIMER && revt[i].ident == 1) {
- continue; /* XXX: start missing procs here */
+ }
+ } else if (revt[i].filter == EVFILT_TIMER) {
+ if (revt[i].ident == 1) {
+ start_dead();
+ }
+ } else {
+ fprintf(stderr, "Unknown event\n");
}
}
}
@@ -383,6 +480,8 @@ end:
if (close(lock_fd) == -1)
perror("close()");
+ reset_signals();
+
reap_all();
return 0;