diff options
Diffstat (limited to 'src/supervision/s6-notifyoncheck.c')
| -rw-r--r-- | src/supervision/s6-notifyoncheck.c | 210 |
1 files changed, 129 insertions, 81 deletions
diff --git a/src/supervision/s6-notifyoncheck.c b/src/supervision/s6-notifyoncheck.c index 8c139af..f86b1e0 100644 --- a/src/supervision/s6-notifyoncheck.c +++ b/src/supervision/s6-notifyoncheck.c @@ -7,10 +7,11 @@ #include <limits.h> #include <sys/wait.h> +#include <skalibs/posixplz.h> #include <skalibs/types.h> #include <skalibs/allreadwrite.h> #include <skalibs/bytestr.h> -#include <skalibs/sgetopt.h> +#include <skalibs/gol.h> #include <skalibs/strerr.h> #include <skalibs/tai.h> #include <skalibs/cspawn.h> @@ -23,15 +24,31 @@ #ifdef S6_USE_EXECLINE #include <execline/config.h> -#define USAGE "s6-notifyoncheck [ -d ] [ -3 fd ] [ -s initialsleep ] [ -T globaltimeout ] [ -t localtimeout ] [ -w waitingtime ] [ -n tries ] [ -c \"checkprog...\" ] prog..." -#define OPTIONS "d3:s:T:t:w:n:c:" +# define USAGE "s6-notifyoncheck [ -d ] [ -3 fd ] [ -s initialsleep ] [ -T globaltimeout ] [ -t localtimeout ] [ -w waitingtime ] [ -n tries ] [ -c \"checkprog...\" ] prog..." #else -#define USAGE "s6-notifyoncheck [ -d ] [ -3 fd ] [ -s initialsleep ] [ -T globaltimeout ] [ -t localtimeout ] [ -w waitingtime ] [ -n tries ] prog..." -#define OPTIONS "d3:s:T:t:w:n:" +# define USAGE "s6-notifyoncheck [ -d ] [ -3 fd ] [ -s initialsleep ] [ -T globaltimeout ] [ -t localtimeout ] [ -w waitingtime ] [ -n tries ] prog..." #endif #define dieusage() strerr_dieusage(100, USAGE) +enum golb_e +{ + GOLB_DOUBLEFORK = 0x01, +} ; + +enum gola_e +{ + GOLA_NOTIF, + GOLA_INITIALSLEEP, + GOLA_GLOBALTIMEOUT, + GOLA_LOCALTIMEOUT, + GOLA_WAITINGTIME, + GOLA_TRIES, +#ifdef S6_USE_EXECLINE + GOLA_CHECKPROG, +#endif + GOLA_N +} ; static inline int read_uint (char const *file, unsigned int *fd) { @@ -65,97 +82,128 @@ static inline int handle_signals (pid_t pid, int *w) } } -static int handle_event (ftrigr_t *a, uint16_t id, pid_t pid) +static int handle_event (ftrigr *a, uint32_t id, pid_t pid) { int r ; - char what ; - if (ftrigr_update(a) < 0) strerr_diefu1sys(111, "ftrigr_update") ; - r = ftrigr_check(a, id, &what) ; - if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ; - if (r && what == 'd') + struct iovec v ; + if (ftrigr_update(a) == -1) strerr_diefu1sys(111, "ftrigr_update") ; + r = ftrigr_peek(a, id, &v) ; + if (r == -1) strerr_diefu1sys(111, "ftrigr_check") ; + if (r) { - if (pid) kill(pid, SIGTERM) ; - return 1 ; + if (memchr(v.iov_base, 'd', v.iov_len)) + { + if (pid) kill(pid, SIGTERM) ; + ftrigr_ack(a, id) ; + return 1 ; + } + ftrigr_ack(a, id) ; } return 0 ; } -int main (int argc, char const *const *argv, char const *const *envp) +int main (int argc, char const *const *argv) { - ftrigr_t a = FTRIGR_ZERO ; - iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .events = IOPAUSE_READ } } ; - char const *childargv[4] = { "./data/check", 0, 0, 0 } ; + static gol_bool rgolb[] = + { + { .so = 'd', .lo = "doublefork", .clear = 0, .set = GOLB_DOUBLEFORK }, + } ; + static gol_arg rgola[] = + { + { .so = '3', .lo = "notification-fd", .i = GOLA_NOTIF }, + { .so = 's', .lo = "initial-sleep", .i = GOLA_INITIALSLEEP }, + { .so = 'T', .lo = "global-timeout", .i = GOLA_GLOBALTIMEOUT }, + { .so = 't', .lo = "local-timeout", .i = GOLA_LOCALTIMEOUT }, + { .so = 'w', .lo = "waiting-time", .i = GOLA_WAITINGTIME }, + { .so = 'n', .lo = "tries", .i = GOLA_TRIES }, #ifdef S6_USE_EXECLINE - char const *checkprog = 0 ; + { .so = 'c', .lo = "check-program", .i = GOLA_CHECKPROG }, #endif + } ; + uint64_t wgolb = 0 ; + char const *wgola[GOLA_N] = { 0 } ; + ftrigr a = FTRIGR_ZERO ; + iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .events = IOPAUSE_READ } } ; + char const *childargv[4] = { "./data/check", 0, 0, 0 } ; unsigned int fd ; - int df = 0 ; - int autodetect = 1 ; int p[2] ; - tain globaldeadline, sleeptto, localtto, waittto ; - unsigned int tries = 7 ; - uint16_t id ; + tain sleeptto ; + tain globaldeadline = TAIN_INFINITE_RELATIVE ; + tain localtto = TAIN_INFINITE_RELATIVE ; + tain waittto = TAIN_INFINITE_RELATIVE ; + unsigned int tries ; + uint32_t id ; + unsigned int golc ; + PROG = "s6-notifyoncheck" ; + golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ; + argc -= golc ; argv += golc ; + if (!argc) dieusage() ; + if (wgola[GOLA_NOTIF]) { - subgetopt l = SUBGETOPT_ZERO ; - unsigned int initialsleep = 10, globaltimeout = 0, localtimeout = 0, waitingtime = 1000 ; - for (;;) - { - int opt = subgetopt_r(argc, argv, OPTIONS, &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'd' : df = 1 ; break ; - case '3' : if (!uint0_scan(l.arg, &fd)) dieusage() ; autodetect = 0 ; break ; - case 's' : if (!uint0_scan(l.arg, &initialsleep)) dieusage() ; break ; - case 'T' : if (!uint0_scan(l.arg, &globaltimeout)) dieusage() ; break ; - case 't' : if (!uint0_scan(l.arg, &localtimeout)) dieusage() ; break ; - case 'w' : if (!uint0_scan(l.arg, &waitingtime)) dieusage() ; break ; - case 'n' : if (!uint0_scan(l.arg, &tries)) dieusage() ; break ; -#ifdef S6_USE_EXECLINE - case 'c' : checkprog = l.arg ; break ; -#endif - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; - if (!argc) dieusage() ; - - if (!tain_from_millisecs(&sleeptto, initialsleep)) dieusage() ; - if (globaltimeout) tain_from_millisecs(&globaldeadline, globaltimeout) ; - else globaldeadline = tain_infinite_relative ; - if (localtimeout) tain_from_millisecs(&localtto, localtimeout) ; - else localtto = tain_infinite_relative ; - if (waitingtime) tain_from_millisecs(&waittto, waitingtime) ; - else waittto = tain_infinite_relative ; - if (!tries) tries = UINT_MAX ; + if (!uint0_scan(wgola[GOLA_NOTIF], &fd)) + strerr_dief2x(100, "notification-fd", " must be an unsigned integer") ; } + else + { + int r = read_uint("notification-fd", &fd) ; + if (r < 0) strerr_diefu2sys(111, "read ", "./notification-fd") ; + if (!r) strerr_dief2x(100, "invalid ", "./notification-fd") ; + } + if (fcntl(fd, F_GETFD) < 0) + strerr_dief2sys(111, "notification-fd", " sanity check failed") ; + if (wgola[GOLA_INITIALSLEEP]) + { + if (!uint0_scan(wgola[GOLA_INITIALSLEEP], &tries)) + strerr_dief2x(100, "initial-sleep", " must be an unsigned integer") ; + } + else tries = 10 ; + if (!tain_from_millisecs(&sleeptto, tries)) dieusage() ; + if (wgola[GOLA_GLOBALTIMEOUT]) { - int r = s6_svc_ok(".") ; - if (r < 0) strerr_diefu1sys(111, "sanity-check current service directory") ; - if (!r) strerr_dief1x(100, "s6-supervise not running.") ; + if (!uint0_scan(wgola[GOLA_GLOBALTIMEOUT], &tries)) + strerr_dief2x(100, "global-timeout", " must be an unsigned integer") ; + if (tries) tain_from_millisecs(&globaldeadline, tries) ; + } + if (wgola[GOLA_LOCALTIMEOUT]) + { + if (!uint0_scan(wgola[GOLA_LOCALTIMEOUT], &tries)) + strerr_dief2x(100, "local-timeout", " must be an unsigned integer") ; + if (tries) tain_from_millisecs(&localtto, tries) ; + } + if (wgola[GOLA_WAITINGTIME]) + { + if (!uint0_scan(wgola[GOLA_WAITINGTIME], &tries)) + strerr_dief2x(100, "waiting-time", " must be an unsigned integer") ; } + else tries = 1000 ; + if (!tain_from_millisecs(&waittto, tries)) dieusage() ; + if (wgola[GOLA_TRIES]) + { + if (!uint0_scan(wgola[GOLA_TRIES], &tries)) + strerr_dief2x(100, "waiting-time", " must be an unsigned integer") ; + if (!tries) tries = UINT_MAX ; + } + else tries = 7 ; + #ifdef S6_USE_EXECLINE - if (checkprog) + if (wgola[GOLA_CHECKPROG]) { childargv[0] = EXECLINE_EXTBINPREFIX "execlineb" ; childargv[1] = "-Pc" ; - childargv[2] = checkprog ; + childargv[2] = wgola[GOLA_CHECKPROG] ; } #endif - if (autodetect) { - int r = read_uint("notification-fd", &fd) ; - if (r < 0) strerr_diefu2sys(111, "read ", "./notification-fd") ; - if (!r) strerr_dief2x(100, "invalid ", "./notification-fd") ; + int r = s6_svc_ok(".") ; + if (r < 0) strerr_diefu1sys(111, "sanity-check current service directory") ; + if (!r) strerr_dief1x(100, "s6-supervise not running.") ; } - if (fcntl(fd, F_GETFD) < 0) - strerr_dief2sys(111, "notification-fd", " sanity check failed") ; - tain_now_set_stopwatch_g() ; + if (!tain_now_set_stopwatch_g()) strerr_diefu1sys(111, "tain_now") ; tain_add_g(&globaldeadline, &globaldeadline) ; @@ -179,16 +227,16 @@ int main (int argc, char const *const *argv, char const *const *envp) */ if (pipecoe(p) < 0) strerr_diefu1sys(111, "pipe") ; - switch (df ? doublefork() : fork()) + switch (wgolb & GOLB_DOUBLEFORK ? doublefork() : fork()) { - case -1: strerr_diefu1sys(111, df ? "doublefork" : "fork") ; + case -1 : strerr_diefu1sys(111, wgolb & GOLB_DOUBLEFORK ? "doublefork" : "fork") ; case 0 : break ; default: { char c ; - close((int)fd) ; + close(fd) ; if (read(p[0], &c, 1) < 1) strerr_diefu1x(111, "synchronize with child") ; - xexec_e(argv, envp) ; + xexec(argv) ; } } @@ -197,11 +245,11 @@ int main (int argc, char const *const *argv, char const *const *envp) close(p[0]) ; if (!ftrigr_startf_g(&a, &globaldeadline)) strerr_diefu1sys(111, "ftrigr_startf") ; - id = ftrigr_subscribe_g(&a, "event", "d", 0, &globaldeadline) ; - if (!id) strerr_diefu1sys(111, "ftrigr_subscribe to event fifodir") ; + if (!ftrigr_subscribe_g(&a, &id, 0, 0, "event", "d", &globaldeadline)) + strerr_diefu1sys(111, "ftrigr_subscribe to event fifodir") ; x[0].fd = selfpipe_init() ; - if (x[0].fd < 0) strerr_diefu1sys(111, "selfpipe_init") ; + if (x[0].fd == -1) strerr_diefu1sys(111, "selfpipe_init") ; if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "trap SIGCHLD") ; x[1].fd = ftrigr_fd(&a) ; @@ -225,13 +273,13 @@ int main (int argc, char const *const *argv, char const *const *envp) if (r < 0) strerr_diefu1sys(111, "iopause") ; if (!r) { - if (!tain_future(&globaldeadline)) return 3 ; + if (!tain_future(&globaldeadline)) _exit(3) ; else break ; } - if (handle_event(&a, id, 0)) return 2 ; + if (handle_event(&a, id, 0)) _exit(2) ; } - pid = cspawn(childargv[0], childargv, envp, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ; + pid = cspawn(childargv[0], childargv, (char const *const *)environ, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ; if (!pid) { strerr_warnwu2sys("spawn ", childargv[0]) ; @@ -249,7 +297,7 @@ int main (int argc, char const *const *argv, char const *const *envp) if (!tain_future(&globaldeadline)) { kill(pid, SIGTERM) ; - return 3 ; + _exit(3) ; } else break ; } @@ -261,14 +309,14 @@ int main (int argc, char const *const *argv, char const *const *envp) if (WIFEXITED(wstat) && !WEXITSTATUS(wstat)) { fd_write((int)fd, "\n", 1) ; - return 0 ; + _exit(0) ; } else break ; } } - if (x[1].revents & IOPAUSE_READ && handle_event(&a, id, pid)) return 2 ; + if (x[1].revents & IOPAUSE_READ && handle_event(&a, id, pid)) _exit(2) ; } } - return 1 ; + _exit(1) ; } |
