diff options
author | Marius Halden <marius.h@lden.org> | 2015-11-27 03:25:38 +0100 |
---|---|---|
committer | Marius Halden <marius.h@lden.org> | 2015-11-27 03:25:38 +0100 |
commit | f1c5678d757e4b945ad044042897bd5ee340900f (patch) | |
tree | f1a473cbba112cefcac16467b390fe8050ee2bb1 /scan.c | |
parent | 78b219eb5869349e9bb01b0abd59b6a944832d90 (diff) | |
download | svcmon-f1c5678d757e4b945ad044042897bd5ee340900f.tar.gz svcmon-f1c5678d757e4b945ad044042897bd5ee340900f.tar.bz2 svcmon-f1c5678d757e4b945ad044042897bd5ee340900f.tar.xz |
Add timout before restart
Diffstat (limited to 'scan.c')
-rw-r--r-- | scan.c | 169 |
1 files changed, 134 insertions, 35 deletions
@@ -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; |