diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2015-07-20 20:20:54 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2015-07-20 20:20:54 +0000 |
commit | a3cdeecf0033919e3b5a79c17c19b5ac98719256 (patch) | |
tree | 92a930930f18a4f8ae897b1a69c39358137ce1e2 /src | |
parent | bd34de9054cec794d96b0fde1eee9100e1d34215 (diff) | |
download | s6-a3cdeecf0033919e3b5a79c17c19b5ac98719256.tar.xz |
- Add timeout-finish support and "down-readiness"
- LOTS of refactoring to make this work
- Remove s6-notifywhenup
- s6-supervise now rocks the casbah
- rc for 2.2.0.0
Diffstat (limited to 'src')
-rw-r--r-- | src/include/s6/s6-supervise.h | 23 | ||||
-rw-r--r-- | src/libs6/deps-lib/s6 | 1 | ||||
-rw-r--r-- | src/libs6/s6_svc_writectl.c | 16 | ||||
-rw-r--r-- | src/libs6/s6_svstatus_pack.c | 15 | ||||
-rw-r--r-- | src/libs6/s6_svstatus_unpack.c | 37 | ||||
-rw-r--r-- | src/supervision/deps-exe/s6-notifywhenup | 3 | ||||
-rw-r--r-- | src/supervision/deps-exe/s6-svlisten | 2 | ||||
-rw-r--r-- | src/supervision/deps-exe/s6-svlisten1 | 2 | ||||
-rw-r--r-- | src/supervision/deps-exe/s6-svwait | 1 | ||||
-rw-r--r-- | src/supervision/s6-notifywhenup.c | 99 | ||||
-rw-r--r-- | src/supervision/s6-supervise.c | 155 | ||||
-rw-r--r-- | src/supervision/s6-svc.c | 27 | ||||
-rw-r--r-- | src/supervision/s6-svlisten.c | 114 | ||||
-rw-r--r-- | src/supervision/s6-svlisten.h | 29 | ||||
-rw-r--r-- | src/supervision/s6-svlisten1.c | 102 | ||||
-rw-r--r-- | src/supervision/s6-svscanctl.c | 12 | ||||
-rw-r--r-- | src/supervision/s6-svstat.c | 31 | ||||
-rw-r--r-- | src/supervision/s6-svwait.c | 92 | ||||
-rw-r--r-- | src/supervision/s6_svlisten_loop.c | 78 | ||||
-rw-r--r-- | src/supervision/s6_svlisten_signal_handler.c | 29 |
20 files changed, 346 insertions, 522 deletions
diff --git a/src/include/s6/s6-supervise.h b/src/include/s6/s6-supervise.h index 2e9a3fa..dec0455 100644 --- a/src/include/s6/s6-supervise.h +++ b/src/include/s6/s6-supervise.h @@ -3,39 +3,44 @@ #ifndef S6_SUPERVISE_H #define S6_SUPERVISE_H +#include <sys/types.h> #include <skalibs/tai.h> #define S6_SUPERVISE_CTLDIR "supervise" #define S6_SUPERVISE_EVENTDIR "event" #define S6_SVSCAN_CTLDIR ".s6-svscan" #define S6_SVSTATUS_FILENAME S6_SUPERVISE_CTLDIR "/status" -#define S6_SUPERVISE_READY_FILENAME S6_SUPERVISE_CTLDIR "/ready" -#define S6_SVSTATUS_SIZE 26 +#define S6_SVSTATUS_SIZE 35 extern int s6_svc_write (char const *, char const *, unsigned int) ; +extern int s6_svc_writectl (char const *, char const *, char const *, unsigned int) ; extern int s6_svc_main (int, char const *const *, char const *, char const *, char const *) ; typedef struct s6_svstatus_s s6_svstatus_t, *s6_svstatus_t_ref ; struct s6_svstatus_s { tain_t stamp ; - unsigned int pid ; - unsigned int flagwant : 1 ; - unsigned int flagwantup : 1 ; + tain_t readystamp ; + pid_t pid ; + int wstat ; unsigned int flagpaused : 1 ; unsigned int flagfinishing : 1 ; - unsigned int wstat ; + unsigned int flagwant : 1 ; + unsigned int flagwantup : 1 ; + unsigned int flagready : 1 ; } ; #define S6_SVSTATUS_ZERO \ { \ .stamp = TAIN_ZERO, \ + .readystamp = TAIN_ZERO, \ .pid = 0, \ - .flagwant = 0, \ - .flagwantup = 0, \ + .wstat = 0, \ .flagpaused = 0, \ .flagfinishing = 0, \ - .wstat = 0 \ + .flagwant = 1, \ + .flagwantup = 1, \ + .flagready = 1 \ } extern void s6_svstatus_pack (char *, s6_svstatus_t const *) ; diff --git a/src/libs6/deps-lib/s6 b/src/libs6/deps-lib/s6 index 01b67c3..093db6a 100644 --- a/src/libs6/deps-lib/s6 +++ b/src/libs6/deps-lib/s6 @@ -26,6 +26,7 @@ s6_accessrules_uidgid_fs.o s6_supervise_lock.o s6_supervise_lock_mode.o s6_svc_write.o +s6_svc_writectl.o s6_svstatus_pack.o s6_svstatus_read.o s6_svstatus_unpack.o diff --git a/src/libs6/s6_svc_writectl.c b/src/libs6/s6_svc_writectl.c new file mode 100644 index 0000000..2e308b9 --- /dev/null +++ b/src/libs6/s6_svc_writectl.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <skalibs/bytestr.h> +#include <s6/s6-supervise.h> + +int s6_svc_writectl (char const *service, char const *subdir, char const *s, unsigned int len) +{ + unsigned int svlen = str_len(service) ; + unsigned int sublen = str_len(subdir) ; + char fn[svlen + sublen + 10] ; + byte_copy(fn, svlen, service) ; + fn[svlen] = '/' ; + byte_copy(fn + svlen + 1, sublen, subdir) ; + byte_copy(fn + svlen + 1 + sublen, 9, "/control") ; + return s6_svc_write(fn, s, len) ; +} diff --git a/src/libs6/s6_svstatus_pack.c b/src/libs6/s6_svstatus_pack.c index 2b1f102..cc92621 100644 --- a/src/libs6/s6_svstatus_pack.c +++ b/src/libs6/s6_svstatus_pack.c @@ -1,6 +1,6 @@ /* ISC license. */ -#include <skalibs/uint32.h> +#include <skalibs/uint16.h> #include <skalibs/uint64.h> #include <skalibs/tai.h> #include <s6/s6-supervise.h> @@ -8,8 +8,13 @@ void s6_svstatus_pack (char *pack, s6_svstatus_t const *sv) { tain_pack(pack, &sv->stamp) ; - uint32_pack(pack + 12, (uint32)sv->pid) ; - pack[16] = sv->flagpaused | (sv->flagfinishing << 1) ; - pack[17] = sv->flagwant ? sv->flagwantup ? 'u' : 'd' : 0 ; - uint64_pack(pack + 18, (uint64)sv->wstat) ; + tain_pack(pack + 12, &sv->readystamp) ; + uint64_pack_big(pack + 24, (uint64)sv->pid) ; + uint16_pack_big(pack + 32, (uint16)sv->wstat) ; + pack[34] = + sv->flagpaused | + (sv->flagfinishing << 1) | + (sv->flagwant << 2) | + (sv->flagwantup << 3) | + (sv->flagready << 4) ; } diff --git a/src/libs6/s6_svstatus_unpack.c b/src/libs6/s6_svstatus_unpack.c index 3fbc205..2e78dcb 100644 --- a/src/libs6/s6_svstatus_unpack.c +++ b/src/libs6/s6_svstatus_unpack.c @@ -1,33 +1,24 @@ /* ISC license. */ -#include <skalibs/uint32.h> +#include <sys/types.h> +#include <skalibs/uint16.h> #include <skalibs/uint64.h> #include <skalibs/tai.h> #include <s6/s6-supervise.h> void s6_svstatus_unpack (char const *pack, s6_svstatus_t *sv) { - uint32 pid ; - uint64 wstat ; + uint64 pid ; + uint16 wstat ; tain_unpack(pack, &sv->stamp) ; - uint32_unpack(pack + 12, &pid) ; - sv->pid = (unsigned int)pid ; - uint64_unpack(pack + 18, &wstat) ; - sv->wstat = (unsigned int)wstat ; - sv->flagpaused = pack[16] & 1 ; - sv->flagfinishing = (pack[16] >> 1) & 1 ; - switch (pack[17]) - { - case 'u' : - sv->flagwant = 1 ; - sv->flagwantup = 1 ; - break ; - case 'd' : - sv->flagwant = 1 ; - sv->flagwantup = 0 ; - break ; - default : - sv->flagwant = 0 ; - sv->flagwantup = 0 ; - } + tain_unpack(pack + 12, &sv->readystamp) ; + uint64_unpack_big(pack + 24, &pid) ; + sv->pid = (pid_t)pid ; + uint16_unpack_big(pack + 32, &wstat) ; + sv->wstat = (int)wstat ; + sv->flagpaused = pack[34] & 1 ; + sv->flagfinishing = !!(pack[34] & 2) ; + sv->flagwant = !!(pack[34] & 4) ; + sv->flagwantup = !!(pack[34] & 8) ; + sv->flagready = !!(pack[34] & 16) ; } diff --git a/src/supervision/deps-exe/s6-notifywhenup b/src/supervision/deps-exe/s6-notifywhenup deleted file mode 100644 index 077e863..0000000 --- a/src/supervision/deps-exe/s6-notifywhenup +++ /dev/null @@ -1,3 +0,0 @@ -${LIBS6} --lskarnet -${TAINNOW_LIB} diff --git a/src/supervision/deps-exe/s6-svlisten b/src/supervision/deps-exe/s6-svlisten index 3bbf778..064975d 100644 --- a/src/supervision/deps-exe/s6-svlisten +++ b/src/supervision/deps-exe/s6-svlisten @@ -1,3 +1,5 @@ +s6_svlisten_signal_handler.o +s6_svlisten_loop.o ${LIBS6} -lexecline -lskarnet diff --git a/src/supervision/deps-exe/s6-svlisten1 b/src/supervision/deps-exe/s6-svlisten1 index f3a3143..656be3e 100644 --- a/src/supervision/deps-exe/s6-svlisten1 +++ b/src/supervision/deps-exe/s6-svlisten1 @@ -1,3 +1,5 @@ +s6_svlisten_signal_handler.o +s6_svlisten_loop.o ${LIBS6} -lskarnet ${SOCKET_LIB} diff --git a/src/supervision/deps-exe/s6-svwait b/src/supervision/deps-exe/s6-svwait index f3a3143..b71e12f 100644 --- a/src/supervision/deps-exe/s6-svwait +++ b/src/supervision/deps-exe/s6-svwait @@ -1,3 +1,4 @@ +s6_svlisten_loop.o ${LIBS6} -lskarnet ${SOCKET_LIB} diff --git a/src/supervision/s6-notifywhenup.c b/src/supervision/s6-notifywhenup.c deleted file mode 100644 index 8c45926..0000000 --- a/src/supervision/s6-notifywhenup.c +++ /dev/null @@ -1,99 +0,0 @@ -/* ISC license. */ - -#include <unistd.h> -#include <errno.h> -#include <skalibs/uint.h> -#include <skalibs/bytestr.h> -#include <skalibs/sgetopt.h> -#include <skalibs/strerr2.h> -#include <skalibs/allreadwrite.h> -#include <skalibs/tai.h> -#include <skalibs/iopause.h> -#include <skalibs/djbunix.h> -#include <s6/ftrigw.h> -#include <s6/s6-supervise.h> - -#define USAGE "s6-notifywhenup [ -d fd ] [ -e fifodir ] [ -f ] [ -X ] [ -t timeout ] prog..." -#define dieusage() strerr_dieusage(100, USAGE) - -static int run_child (int fd, char const *fifodir, unsigned int timeout) -{ - char dummy[4096] ; - iopause_fd x = { .fd = fd, .events = IOPAUSE_READ } ; - tain_t deadline ; - char pack[TAIN_PACK] ; - if (!tain_now_g()) strerr_diefu1sys(111, "tain_now") ; - if (timeout) tain_from_millisecs(&deadline, timeout) ; - else deadline = tain_infinite_relative ; - tain_add_g(&deadline, &deadline) ; - for (;;) - { - register int r = iopause_g(&x, 1, &deadline) ; - if (r < 0) strerr_diefu1sys(111, "iopause") ; - if (!r) return 99 ; - r = sanitize_read(fd_read(fd, dummy, 4096)) ; - if (r < 0) - if (errno == EPIPE) return 1 ; - else strerr_diefu1sys(111, "read from parent") ; - else if (r) - if (byte_chr(dummy, r, '\n') < r) break ; - } - close(fd) ; - tain_pack(pack, &STAMP) ; - if (!openwritenclose_suffix(S6_SUPERVISE_READY_FILENAME, pack, TAIN_PACK, ".new")) - strerr_warnwu1sys("open " S6_SUPERVISE_READY_FILENAME " for writing") ; - ftrigw_notify(fifodir, 'U') ; - return 0 ; -} - -int main (int argc, char const *const *argv, char const *const *envp) -{ - unsigned int fd = 1 ; - char const *fifodir = "event" ; - int df = 1, fake = 0 ; - unsigned int timeout = 0 ; - PROG = "s6-notifywhenup" ; - { - subgetopt_t l = SUBGETOPT_ZERO ; - for (;;) - { - register int opt = subgetopt_r(argc, argv, "Xd:e:ft:", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'X' : fake = 1 ; break ; - case 'd' : if (!uint0_scan(l.arg, &fd)) dieusage() ; break ; - case 'e' : fifodir = l.arg ; break ; - case 'f' : df = 0 ; break ; - case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; - } - if (!argc) dieusage() ; - strerr_warnw1x("this program is deprecated. Use a notification-fd file instead.") ; - - { - int p[2] ; - pid_t pid ; - if (pipe(p) < 0) strerr_diefu1sys(111, "pipe") ; - pid = df ? doublefork() : fork() ; - if (pid < 0) strerr_diefu1sys(111, df ? "doublefork" : "fork") ; - else if (!pid) - { - PROG = "s6-notifywhenup (child)" ; - close(p[1]) ; - return run_child(p[0], fifodir, timeout) ; - } - close(p[0]) ; - if (fd_move((int)fd, p[1]) < 0) strerr_diefu1sys(111, "fd_move") ; - } - if (fake) - { - write(fd, "\n", 1) ; - close(fd) ; - } - pathexec_run(argv[0], argv, envp) ; - strerr_dieexec(111, argv[0]) ; -} diff --git a/src/supervision/s6-supervise.c b/src/supervision/s6-supervise.c index 5ce718f..0f0b256 100644 --- a/src/supervision/s6-supervise.c +++ b/src/supervision/s6-supervise.c @@ -45,18 +45,11 @@ typedef action_t *action_t_ref ; static tain_t deadline ; static tain_t dontrespawnbefore = TAIN_EPOCH ; -static s6_svstatus_t status = { .stamp = TAIN_ZERO, .pid = 0, .flagwant = 1, .flagwantup = 1, .flagpaused = 0, .flagfinishing = 0, .wstat = 0 } ; +static s6_svstatus_t status = S6_SVSTATUS_ZERO ; static state_t state = DOWN ; static int cont = 1 ; static int notifyfd = -1 ; -static inline void down_and_delay (void) -{ - state = DOWN ; - if (tain_future(&dontrespawnbefore)) deadline = dontrespawnbefore ; - else tain_copynow(&deadline) ; -} - static inline void settimeout (int secs) { tain_addsec_g(&deadline, secs) ; @@ -73,6 +66,37 @@ static inline void announce (void) strerr_warnwu1sys("write status file") ; } +static int read_uint (char const *file, unsigned int *fd) +{ + char buf[UINT_FMT + 1] ; + register int r = openreadnclose_nb(file, buf, UINT_FMT) ; + if (r < 0) + { + if (errno != ENOENT) strerr_warnwu2sys("open ", file) ; + return 0 ; + } + buf[byte_chr(buf, r, '\n')] = 0 ; + if (!uint0_scan(buf, fd)) + { + strerr_warnw2x("invalid ", file) ; + return 0 ; + } + return 1 ; +} + +static void set_down_and_ready (char const *s, unsigned int n) +{ + status.pid = 0 ; + status.flagfinishing = 0 ; + status.flagready = 1 ; + tain_copynow(&status.readystamp) ; + state = DOWN ; + if (tain_future(&dontrespawnbefore)) deadline = dontrespawnbefore ; + else tain_copynow(&deadline) ; + announce() ; + ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, s, n) ; +} + /* The action array. */ @@ -183,27 +207,12 @@ static void trystart (void) strerr_warnwu1sys("pipe (waiting 60 seconds)") ; return ; } + if (read_uint("notification-fd", &fd) && pipe(notifyp) < 0) { - char buf[UINT_FMT + 1] ; - register int r = openreadnclose("notification-fd", buf, UINT_FMT) ; - if (r < 0) - { - if (errno != ENOENT) - strerr_warnwu1sys("open notification-fd") ; - } - else - { - buf[byte_chr(buf, r, '\n')] = 0 ; - if (!uint0_scan(buf, &fd)) - strerr_warnw1x("invalid notification-fd") ; - else if (pipe(notifyp) < 0) - { - settimeout(60) ; - strerr_warnwu1sys("pipe (waiting 60 seconds)") ; - fd_close(p[1]) ; fd_close(p[0]) ; - return ; - } - } + settimeout(60) ; + strerr_warnwu1sys("pipe (waiting 60 seconds)") ; + fd_close(p[1]) ; fd_close(p[0]) ; + return ; } pid = fork() ; if (pid < 0) @@ -222,8 +231,6 @@ static void trystart (void) selfpipe_finish() ; if (notifyp[0] >= 0) close(notifyp[0]) ; close(p[0]) ; - if (unlink(S6_SUPERVISE_READY_FILENAME) < 0 && errno != ENOENT) - strerr_warnwu1sys("unlink " S6_SUPERVISE_READY_FILENAME) ; if (notifyp[1] >= 0 && fd_move((int)fd, notifyp[1]) < 0) { failcoe(p[1]) ; @@ -264,6 +271,7 @@ static void trystart (void) settimeout_infinite() ; state = UP ; status.pid = pid ; + status.flagready = 0 ; tain_copynow(&status.stamp) ; tain_addsec_g(&dontrespawnbefore, 1) ; announce() ; @@ -303,17 +311,25 @@ static void down_d (void) announce() ; } -static inline void tryfinish (int islast) +static int uplastup_z (void) { - register pid_t pid = fork() ; - if (pid < 0) + status.wstat = (int)status.pid ; + status.flagpaused = 0 ; + status.flagready = 0 ; + tain_copynow(&status.stamp) ; + if (notifyfd >= 0) + { + fd_close(notifyfd) ; + notifyfd = -1 ; + } + status.pid = fork() ; + if (status.pid < 0) { strerr_warnwu2sys("fork for ", "./finish") ; - if (islast) bail() ; - down_and_delay() ; - return ; + set_down_and_ready("dD", 2) ; + return 0 ; } - else if (!pid) + else if (!status.pid) { char fmt0[UINT_FMT] ; char fmt1[UINT_FMT] ; @@ -325,39 +341,35 @@ static inline void tryfinish (int islast) execve("./finish", cargv, (char *const *)environ) ; _exit(127) ; } - status.pid = pid ; status.flagfinishing = 1 ; - state = islast ? LASTFINISH : FINISH ; + announce() ; + ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "d", 1) ; + { + tain_t tto ; + unsigned int timeout ; + if (!read_uint("timeout-finish", &timeout)) timeout = 5000 ; + if (timeout && tain_from_millisecs(&tto, timeout)) + tain_add_g(&deadline, &tto) ; + else settimeout_infinite() ; + } + return 1 ; } -static void uptimeout (void) +static void up_z (void) { - settimeout_infinite() ; - strerr_warnw1x("can't happen: timeout while the service is up!") ; + if (uplastup_z()) state = FINISH ; } -static void uplastup_z (int islast) +static void lastup_z (void) { - status.wstat = status.pid ; - status.pid = 0 ; - tain_copynow(&status.stamp) ; - if (notifyfd >= 0) - { - fd_close(notifyfd) ; - notifyfd = -1 ; - } - tryfinish(islast) ; - announce() ; - ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "d", 1) ; - if (unlink(S6_SUPERVISE_READY_FILENAME) < 0 && errno != ENOENT) - strerr_warnwu1sys("unlink " S6_SUPERVISE_READY_FILENAME) ; - settimeout(5) ; + if (uplastup_z()) state = LASTFINISH ; + else bail() ; } -static void up_z (void) +static void uptimeout (void) { - status.flagpaused = 0 ; - uplastup_z(0) ; + settimeout_infinite() ; + strerr_warnw1x("can't happen: timeout while the service is up!") ; } static void up_o (void) @@ -400,17 +412,14 @@ static void up_term (void) static void finishtimeout (void) { - strerr_warnw1x("finish script takes too long - killing it") ; + strerr_warnw1x("finish script lifetime reached maximum value - sending it a SIGKILL") ; killc() ; killk() ; - settimeout(3) ; + settimeout(5) ; } static void finish_z (void) { - status.pid = 0 ; - status.flagfinishing = 0 ; - down_and_delay() ; - announce() ; + set_down_and_ready("D", 1) ; } static void finish_u (void) @@ -431,11 +440,6 @@ static void finish_X (void) finish_x() ; } -static void lastup_z (void) -{ - uplastup_z(1) ; -} - static action_t_ref const actions[5][24] = { { &downtimeout, &nop, &bail, &bail, &bail, @@ -470,10 +474,9 @@ static inline void handle_notifyfd (void) r = sanitize_read(fd_read(notifyfd, buf, 4096)) ; if (r > 0 && byte_chr(buf, r, '\n') < r) { - char pack[TAIN_PACK] ; - tain_pack(pack, &STAMP) ; - if (!openwritenclose_suffix(S6_SUPERVISE_READY_FILENAME, pack, TAIN_PACK, ".new")) - strerr_warnwu3sys("open ", S6_SUPERVISE_READY_FILENAME, " for writing") ; + tain_copynow(&status.readystamp) ; + status.flagready = 1 ; + announce() ; ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "U", 1) ; r = -1 ; } @@ -504,7 +507,7 @@ static inline void handle_signals (void) if (errno != ECHILD) strerr_diefu1sys(111, "wait_pid_nohang") ; else break ; else if (!r) break ; - status.pid = wstat ; /* don't overwrite status.wstat if it's ./finish */ + status.pid = (pid_t)wstat ; /* don't overwrite status.wstat if it's ./finish */ (*actions[state][V_CHLD])() ; } break ; diff --git a/src/supervision/s6-svc.c b/src/supervision/s6-svc.c index 047d44d..308075d 100644 --- a/src/supervision/s6-svc.c +++ b/src/supervision/s6-svc.c @@ -10,7 +10,7 @@ #include <s6/config.h> #include <s6/s6-supervise.h> -#define USAGE "s6-svc [ -D | -U ] [ -T timeout ] [ -abqhkti12pcoduxOX ] servicedir" +#define USAGE "s6-svc [ -wu | -wU | -wd | -wD ] [ -T timeout ] [ -abqhkti12pcoduxOX ] servicedir" #define dieusage() strerr_dieusage(100, USAGE) #define DATASIZE 63 @@ -26,12 +26,10 @@ int main (int argc, char const *const *argv, char const *const *envp) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - register int opt = subgetopt_r(argc, argv, "DUabqhkti12pcoduxOXT:", &l) ; + register int opt = subgetopt_r(argc, argv, "abqhkti12pcoduxOXT:w:", &l) ; if (opt == -1) break ; switch (opt) { - case 'D' : updown[1] = 'd' ; break ; - case 'U' : updown[1] = 'U' ; break ; case 'a' : case 'b' : case 'q' : @@ -55,6 +53,12 @@ int main (int argc, char const *const *argv, char const *const *envp) break ; } case 'T' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + case 'w' : + { + if (byte_chr("dDuU", 4, l.arg[0]) >= 4) dieusage() ; + updown[1] = l.arg[0] ; + break ; + } default : dieusage() ; } } @@ -63,6 +67,7 @@ int main (int argc, char const *const *argv, char const *const *envp) if (!argc) dieusage() ; if (argc > 1) strerr_warn1x("ignoring extra arguments") ; + if (datalen <= 1) return 0 ; if (updown[1] == 'U') { unsigned int arglen = str_len(argv[0]) ; @@ -72,8 +77,8 @@ int main (int argc, char const *const *argv, char const *const *envp) if (access(fn, F_OK) < 0) { if (errno != ENOENT) strerr_diefu2sys(111, "access ", fn) ; - updown[1] = 0 ; - strerr_warnw2x(fn, " not present - ignoring -U option") ; + updown[1] = 'u' ; + strerr_warnw2x(fn, " not present - converting -wU to -wu") ; } } @@ -100,15 +105,9 @@ int main (int argc, char const *const *argv, char const *const *envp) pathexec_run(newargv[0], newargv, envp) ; strerr_dieexec(111, newargv[0]) ; } - else if (datalen > 1) + else { - unsigned int arglen = str_len(argv[0]) ; - char tmp[arglen + 9 + sizeof(S6_SUPERVISE_CTLDIR)] ; - register int r ; - byte_copy(tmp, arglen, argv[0]) ; - tmp[arglen] = '/' ; - byte_copy(tmp + arglen + 1, 8 + sizeof(S6_SUPERVISE_CTLDIR), S6_SUPERVISE_CTLDIR "/control") ; - r = s6_svc_write(tmp, data + 1, datalen - 1) ; + register int r = s6_svc_writectl(argv[0], S6_SUPERVISE_CTLDIR, data + 1, datalen - 1) ; if (r < 0) strerr_diefu2sys(111, "control ", argv[0]) ; else if (!r) strerr_diefu3x(100, "control ", argv[0], ": supervisor not listening") ; } diff --git a/src/supervision/s6-svlisten.c b/src/supervision/s6-svlisten.c index 709c409..1241d72 100644 --- a/src/supervision/s6-svlisten.c +++ b/src/supervision/s6-svlisten.c @@ -1,64 +1,40 @@ /* ISC license. */ #include <sys/types.h> -#include <unistd.h> -#include <errno.h> #include <skalibs/sgetopt.h> -#include <skalibs/bytestr.h> #include <skalibs/uint16.h> #include <skalibs/uint.h> #include <skalibs/bitarray.h> #include <skalibs/tai.h> #include <skalibs/strerr2.h> -#include <skalibs/iopause.h> #include <skalibs/djbunix.h> -#include <skalibs/sig.h> -#include <skalibs/selfpipe.h> #include <execline/execline.h> -#include <s6/ftrigr.h> -#include <s6/s6-supervise.h> +#include "s6-svlisten.h" -#define USAGE "s6-svlisten [ -U | -u | -d ] [ -A | -a | -o ] [ -t timeout ] servicedir... \"\" prog..." +#define USAGE "s6-svlisten [ -U | -u | -d | -D ] [ -a | -o ] [ -t timeout ] servicedir... \"\" prog..." #define dieusage() strerr_dieusage(100, USAGE) -static inline int check (unsigned char const *ba, unsigned int n, int wantup, int or) -{ - return (bitarray_first(ba, n, or == wantup) < n) == or ; -} - -static void handle_signals (void) -{ - for (;;) switch (selfpipe_read()) - { - case -1 : strerr_diefu1sys(111, "selfpipe_read") ; - case 0 : return ; - case SIGCHLD : wait_reap() ; break ; - default : strerr_dief1x(101, "unexpected data in selfpipe") ; - } -} - int main (int argc, char const **argv, char const *const *envp) { - ftrigr_t a = FTRIGR_ZERO ; tain_t deadline, tto ; int spfd ; int argc1 ; int or = 0 ; - int wantup = 1 ; - char re[4] = "u|d" ; + int wantup = 1, wantready = 0 ; PROG = "s6-svlisten" ; { subgetopt_t l = SUBGETOPT_ZERO ; unsigned int t = 0 ; for (;;) { - register int opt = subgetopt_r(argc, argv, "uUdAaot:", &l) ; + register int opt = subgetopt_r(argc, argv, "uUdDaot:", &l) ; if (opt == -1) break ; switch (opt) { - case 'U' : wantup = 1 ; re[0] = 'U' ; break ; - case 'u' : wantup = 1 ; re[0] = 'u' ; break ; - case 'd' : wantup = 0 ; break ; + case 'u' : wantup = 1 ; wantready = 0 ; break ; + case 'U' : wantup = 1 ; wantready = 1 ; break ; + case 'd' : wantup = 0 ; wantready = 0 ; break ; + case 'D' : wantup = 0 ; wantready = 1 ; break ; case 'a' : or = 0 ; break ; case 'o' : or = 1 ; break ; case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; @@ -74,79 +50,19 @@ int main (int argc, char const **argv, char const *const *envp) if (!argc1 || argc == argc1 + 1) dieusage() ; if (argc1 >= argc) strerr_dief1x(100, "unterminated servicedir block") ; - spfd = selfpipe_init() ; - if (spfd < 0) strerr_diefu1sys(111, "selfpipe_init") ; - if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; - if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "sig_ignore") ; - tain_now_g() ; tain_add_g(&deadline, &tto) ; - - if (!ftrigr_startf_g(&a, &deadline)) strerr_diefu1sys(111, "ftrigr_startf") ; + spfd = s6_svlisten_selfpipe_init() ; { - iopause_fd x[2] = { { .fd = spfd, .events = IOPAUSE_READ }, { .fd = ftrigr_fd(&a), .events = IOPAUSE_READ } } ; + s6_svlisten_t foo = S6_SVLISTEN_ZERO ; pid_t pid ; - unsigned int i = 0 ; - uint16 list[argc1] ; - unsigned char states[bitarray_div8(argc1)] ; - for (; i < (unsigned int)argc1 ; i++) - { - unsigned int len = str_len(argv[i]) ; - char s[len + 1 + sizeof(S6_SUPERVISE_EVENTDIR)] ; - byte_copy(s, len, argv[i]) ; - s[len] = '/' ; - byte_copy(s + len + 1, sizeof(S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR) ; - list[i] = ftrigr_subscribe_g(&a, s, re, FTRIGR_REPEAT, &deadline) ; - if (!list[i]) strerr_diefu2sys(111, "subscribe to events for ", argv[i]) ; - } - - for (i = 0 ; i < (unsigned int)argc1 ; i++) - { - s6_svstatus_t st = S6_SVSTATUS_ZERO ; - int isup ; - if (!s6_svstatus_read(argv[i], &st)) strerr_diefu1sys(111, "s6_svstatus_read") ; - isup = !!st.pid ; - if (re[0] == 'U' && isup) - { - unsigned int len = str_len(argv[i]) ; - char s[len + 1 + sizeof(S6_SUPERVISE_READY_FILENAME)] ; - byte_copy(s, len, argv[i]) ; - s[len] = '/' ; - byte_copy(s + len + 1, sizeof(S6_SUPERVISE_READY_FILENAME), S6_SUPERVISE_READY_FILENAME) ; - if (access(s, F_OK) < 0) - { - if (errno == ENOENT) isup = 0 ; - else strerr_warnwu2sys("check ", s) ; - } - } - bitarray_poke(states, i, isup) ; - } - + uint16 ids[argc1] ; + unsigned char upstate[bitarray_div8(argc1)] ; + unsigned char readystate[bitarray_div8(argc1)] ; + s6_svlisten_init(argc1, argv, &foo, ids, upstate, readystate, &deadline) ; pid = child_spawn0(argv[argc1 + 1], argv + argc1 + 1, envp) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ; - - for (;;) - { - register int r ; - if (check(states, argc1, wantup, or)) break ; - r = iopause_g(x, 2, &deadline) ; - if (r < 0) strerr_diefu1sys(111, "iopause") ; - else if (!r) strerr_dief1x(1, "timed out") ; - - if (x[0].revents & IOPAUSE_READ) handle_signals() ; - if (x[1].revents & IOPAUSE_READ) - { - if (ftrigr_update(&a) < 0) strerr_diefu1sys(111, "ftrigr_update") ; - for (i = 0 ; i < (unsigned int)argc1 ; i++) - { - char what ; - register int r = ftrigr_check(&a, list[i], &what) ; - if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ; - if (r) bitarray_poke(states, i, what == re[0]) ; - } - } - } + return s6_svlisten_loop(&foo, wantup, wantready, or, &deadline, spfd, &s6_svlisten_signal_handler) ; } - return 0 ; } diff --git a/src/supervision/s6-svlisten.h b/src/supervision/s6-svlisten.h new file mode 100644 index 0000000..a5d36dd --- /dev/null +++ b/src/supervision/s6-svlisten.h @@ -0,0 +1,29 @@ +/* ISC license. */ + +#ifndef S6_SVLISTEN_H +#define S6_SVLISTEN_H + +#include <skalibs/uint16.h> +#include <skalibs/tai.h> +#include <s6/ftrigr.h> + +typedef void action_func_t (void) ; +typedef action_func_t *action_func_t_ref ; + +typedef struct s6_svlisten_s s6_svlisten_t, *s6_svlisten_t_ref ; +struct s6_svlisten_s +{ + ftrigr_t a ; + unsigned int n ; + uint16 *ids ; + unsigned char *upstate ; + unsigned char *readystate ; +} ; +#define S6_SVLISTEN_ZERO { .a = FTRIGR_ZERO, .n = 0, .ids = 0, .upstate = 0, .readystate = 0 } + +extern void s6_svlisten_signal_handler (void) ; +extern int s6_svlisten_selfpipe_init (void) ; +extern void s6_svlisten_init (int, char const *const *, s6_svlisten_t *, uint16 *, unsigned char *, unsigned char *, tain_t const *) ; +extern int s6_svlisten_loop (s6_svlisten_t *, int, int, int, tain_t const *, int, action_func_t_ref) ; + +#endif diff --git a/src/supervision/s6-svlisten1.c b/src/supervision/s6-svlisten1.c index a5cecf0..32fef1f 100644 --- a/src/supervision/s6-svlisten1.c +++ b/src/supervision/s6-svlisten1.c @@ -1,56 +1,40 @@ /* ISC license. */ #include <sys/types.h> -#include <unistd.h> -#include <errno.h> -#include <signal.h> #include <skalibs/sgetopt.h> -#include <skalibs/bytestr.h> #include <skalibs/uint16.h> #include <skalibs/uint.h> #include <skalibs/tai.h> #include <skalibs/strerr2.h> #include <skalibs/djbunix.h> -#include <skalibs/iopause.h> -#include <skalibs/sig.h> -#include <skalibs/selfpipe.h> -#include <s6/ftrigr.h> -#include <s6/s6-supervise.h> +#include "s6-svlisten.h" -#define USAGE "s6-svlisten1 [ -U | -u | -d ] [ -t timeout ] servicedir prog..." +#define USAGE "s6-svlisten1 [ -U | -u | -d | -D ] [ -t timeout ] servicedir prog..." #define dieusage() strerr_dieusage(100, USAGE) -static void handle_signals (void) -{ - for (;;) switch (selfpipe_read()) - { - case -1 : strerr_diefu1sys(111, "selfpipe_read") ; - case 0 : return ; - case SIGCHLD : wait_reap() ; break ; - default : strerr_dief1x(101, "unexpected data in selfpipe") ; - } -} - int main (int argc, char const *const *argv, char const *const *envp) { - ftrigr_t a = FTRIGR_ZERO ; + s6_svlisten_t foo = S6_SVLISTEN_ZERO ; tain_t deadline, tto ; + pid_t pid ; int spfd ; - int wantup = 1 ; - char re[4] = "u|d" ; + int wantup = 1, wantready = 0 ; + uint16 id ; + unsigned char upstate, readystate ; PROG = "s6-svlisten1" ; { subgetopt_t l = SUBGETOPT_ZERO ; unsigned int t = 0 ; for (;;) { - register int opt = subgetopt_r(argc, argv, "uUdt:", &l) ; + register int opt = subgetopt_r(argc, argv, "uUdDt:", &l) ; if (opt == -1) break ; switch (opt) { - case 'U' : wantup = 1 ; re[0] = 'U' ; break ; - case 'u' : wantup = 1 ; re[0] = 'u' ; break ; - case 'd' : wantup = 0 ; break ; + case 'u' : wantup = 1 ; wantready = 0 ; break ; + case 'U' : wantup = 1 ; wantready = 1 ; break ; + case 'd' : wantup = 0 ; wantready = 0 ; break ; + case 'D' : wantup = 0 ; wantready = 1 ; break ; case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; default : dieusage() ; } @@ -59,63 +43,11 @@ int main (int argc, char const *const *argv, char const *const *envp) if (t) tain_from_millisecs(&tto, t) ; else tto = tain_infinite_relative ; } if (!argc) dieusage() ; - - spfd = selfpipe_init() ; - if (spfd < 0) strerr_diefu1sys(111, "selfpipe_init") ; - if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; - if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "sig_ignore") ; - tain_now_g() ; tain_add_g(&deadline, &tto) ; - - if (!ftrigr_startf_g(&a, &deadline)) strerr_diefu1sys(111, "ftrigr_startf") ; - - { - iopause_fd x[2] = { { .fd = spfd, .events = IOPAUSE_READ }, { .fd = ftrigr_fd(&a), .events = IOPAUSE_READ } } ; - unsigned int arglen = str_len(argv[0]) ; - pid_t pid ; - int isup ; - s6_svstatus_t st = S6_SVSTATUS_ZERO ; - uint16 id ; - char s[arglen + 1 + sizeof(S6_SUPERVISE_EVENTDIR)] ; - byte_copy(s, arglen, argv[0]) ; - s[arglen] = '/' ; - byte_copy(s + arglen + 1, sizeof(S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR) ; - id = ftrigr_subscribe_g(&a, s, re, FTRIGR_REPEAT, &deadline) ; - if (!id) strerr_diefu2sys(111, "subscribe to events for ", argv[0]) ; - if (!s6_svstatus_read(argv[0], &st)) strerr_diefu1sys(111, "s6_svstatus_read") ; - isup = !!st.pid ; - if (re[0] == 'U' && isup) - { - byte_copy(s + arglen + 1, sizeof(S6_SUPERVISE_READY_FILENAME), S6_SUPERVISE_READY_FILENAME) ; - if (access(s, F_OK) < 0) - { - if (errno == ENOENT) isup = 0 ; - else strerr_warnwu2sys("check ", s) ; - } - } - - pid = child_spawn0(argv[1], argv + 1, envp) ; - if (!pid) strerr_diefu2sys(111, "spawn ", argv[2]) ; - - for (;;) - { - register int r ; - if (isup == wantup) break ; - r = iopause_g(x, 2, &deadline) ; - if (r < 0) strerr_diefu1sys(111, "iopause") ; - else if (!r) strerr_dief1x(1, "timed out") ; - - if (x[0].revents & IOPAUSE_READ) handle_signals() ; - if (x[1].revents & IOPAUSE_READ) - { - 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) isup = what == re[0] ; - } - } - } - return 0 ; + spfd = s6_svlisten_selfpipe_init() ; + s6_svlisten_init(1, argv, &foo, &id, &upstate, &readystate, &deadline) ; + pid = child_spawn0(argv[1], argv + 1, envp) ; + if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ; + return s6_svlisten_loop(&foo, wantup, wantready, 1, &deadline, spfd, &s6_svlisten_signal_handler) ; } diff --git a/src/supervision/s6-svscanctl.c b/src/supervision/s6-svscanctl.c index 6529e9c..a991146 100644 --- a/src/supervision/s6-svscanctl.c +++ b/src/supervision/s6-svscanctl.c @@ -52,14 +52,8 @@ int main (int argc, char const *const *argv) } if (!argc) dieusage() ; - { - unsigned int arglen = str_len(*argv) ; - char tmp[arglen + 20] ; - byte_copy(tmp, arglen, *argv) ; - byte_copy(tmp + arglen, 20, "/.s6-svscan/control") ; - r = s6_svc_write(tmp, data, datalen) ; - } - if (r < 0) strerr_diefu2sys(111, "control ", *argv) ; - else if (!r) strerr_diefu3x(100, "control ", *argv, ": supervisor not listening") ; + r = s6_svc_writectl(argv[0], S6_SVSCAN_CTLDIR, data, datalen) ; + if (r < 0) strerr_diefu2sys(111, "control ", argv[0]) ; + else if (!r) strerr_diefu3x(100, "control ", argv[0], ": supervisor not listening") ; return 0 ; } diff --git a/src/supervision/s6-svstat.c b/src/supervision/s6-svstat.c index de8fe0d..bfe87a5 100644 --- a/src/supervision/s6-svstat.c +++ b/src/supervision/s6-svstat.c @@ -1,8 +1,8 @@ /* ISC license. */ #include <sys/types.h> -#include <sys/stat.h> #include <sys/wait.h> +#include <unistd.h> #include <errno.h> #include <skalibs/uint64.h> #include <skalibs/uint.h> @@ -23,7 +23,6 @@ int main (int argc, char const *const *argv) s6_svstatus_t status ; int flagnum = 0 ; int isup, normallyup ; - tain_t readytime = TAIN_ZERO ; char fmt[UINT_FMT] ; PROG = "s6-svstat" ; { @@ -49,26 +48,14 @@ int main (int argc, char const *const *argv) if (tain_future(&status.stamp)) tain_copynow(&status.stamp) ; { - char pack[TAIN_PACK] ; - struct stat st ; unsigned int dirlen = str_len(*argv) ; - char fn[dirlen + sizeof(S6_SUPERVISE_READY_FILENAME) + 1] ; + char fn[dirlen + 6] ; byte_copy(fn, dirlen, *argv) ; byte_copy(fn + dirlen, 6, "/down") ; - if (stat(fn, &st) == -1) - if (errno != ENOENT) strerr_diefu2sys(111, "stat ", fn) ; + if (access(fn, F_OK) < 0) + if (errno != ENOENT) strerr_diefu2sys(111, "access ", fn) ; else normallyup = 1 ; else normallyup = 0 ; - byte_copy(fn + dirlen, sizeof(S6_SUPERVISE_READY_FILENAME) + 1, "/" S6_SUPERVISE_READY_FILENAME) ; - if (openreadnclose(fn, pack, TAIN_PACK) < TAIN_PACK) - { - if (errno != ENOENT) strerr_warnwu2sys("read ", fn) ; - } - else - { - tain_unpack(pack, &readytime) ; - if (tain_future(&readytime)) tain_copynow(&readytime) ; - } } isup = status.pid && !status.flagfinishing ; @@ -110,16 +97,16 @@ int main (int argc, char const *const *argv) buffer_putnoflush(buffer_1small, ", normally up", 13) ; if (isup && status.flagpaused) buffer_putnoflush(buffer_1small, ", paused", 8) ; - if (!isup && (status.flagwant == 'u')) + if (!isup && status.flagwant) buffer_putnoflush(buffer_1small, ", want up", 10) ; - if (isup && (status.flagwant == 'd')) + if (isup && !status.flagwant) buffer_putnoflush(buffer_1small, ", want down", 12) ; - if (readytime.sec.x) + if (status.flagready) { - tain_sub(&readytime, &STAMP, &readytime) ; + tain_sub(&status.readystamp, &STAMP, &status.readystamp) ; buffer_putnoflush(buffer_1small, ", ready ", 8) ; - buffer_putnoflush(buffer_1small, fmt, uint64_fmt(fmt, readytime.sec.x)) ; + buffer_putnoflush(buffer_1small, fmt, uint64_fmt(fmt, status.readystamp.sec.x)) ; buffer_putnoflush(buffer_1small, " seconds", 8) ; } if (buffer_putflush(buffer_1small, "\n", 1) < 0) diff --git a/src/supervision/s6-svwait.c b/src/supervision/s6-svwait.c index fa8d227..1793347 100644 --- a/src/supervision/s6-svwait.c +++ b/src/supervision/s6-svwait.c @@ -1,46 +1,35 @@ /* ISC license. */ -#include <unistd.h> -#include <errno.h> #include <skalibs/sgetopt.h> -#include <skalibs/bytestr.h> #include <skalibs/uint16.h> #include <skalibs/uint.h> #include <skalibs/bitarray.h> #include <skalibs/tai.h> #include <skalibs/strerr2.h> -#include <skalibs/iopause.h> -#include <s6/ftrigr.h> -#include <s6/s6-supervise.h> +#include "s6-svlisten.h" -#define USAGE "s6-svwait [ -U | -u | -d ] [ -a | -o ] [ -t timeout ] servicedir..." +#define USAGE "s6-svwait [ -U | -u | -d | -D ] [ -a | -o ] [ -t timeout ] servicedir..." #define dieusage() strerr_dieusage(100, USAGE) -static inline int check (unsigned char const *ba, unsigned int n, int wantup, int or) -{ - return (bitarray_first(ba, n, or == wantup) < n) == or ; -} - int main (int argc, char const *const *argv) { tain_t deadline, tto ; - ftrigr_t a = FTRIGR_ZERO ; int or = 0 ; - int wantup = 1 ; - char re[4] = "u|d" ; + int wantup = 1, wantready = 0 ; PROG = "s6-svwait" ; { subgetopt_t l = SUBGETOPT_ZERO ; unsigned int t = 0 ; for (;;) { - register int opt = subgetopt_r(argc, argv, "uUdaot:", &l) ; + register int opt = subgetopt_r(argc, argv, "UudDaot:", &l) ; if (opt == -1) break ; switch (opt) { - case 'U' : wantup = 1 ; re[0] = 'U' ; break ; - case 'u' : wantup = 1 ; re[0] = 'u' ; break ; - case 'd' : wantup = 0 ; break ; + case 'U' : wantup = 1 ; wantready = 1 ; break ; + case 'u' : wantup = 1 ; wantready = 0 ; break ; + case 'd' : wantup = 0 ; wantready = 0 ; break ; + case 'D' : wantup = 0 ; wantready = 1 ; break ; case 'a' : or = 0 ; break ; case 'o' : or = 1 ; break ; case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; @@ -55,65 +44,12 @@ int main (int argc, char const *const *argv) tain_now_g() ; tain_add_g(&deadline, &tto) ; - if (!ftrigr_startf_g(&a, &deadline)) strerr_diefu1sys(111, "ftrigr_startf") ; - { - iopause_fd x = { -1, IOPAUSE_READ, 0 } ; - unsigned int i = 0 ; - uint16 list[argc] ; - unsigned char states[bitarray_div8(argc)] ; - x.fd = ftrigr_fd(&a) ; - for (; i < (unsigned int)argc ; i++) - { - unsigned int len = str_len(argv[i]) ; - char s[len + 1 + sizeof(S6_SUPERVISE_EVENTDIR)] ; - byte_copy(s, len, argv[i]) ; - s[len] = '/' ; - byte_copy(s + len + 1, sizeof(S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR) ; - list[i] = ftrigr_subscribe_g(&a, s, re, FTRIGR_REPEAT, &deadline) ; - if (!list[i]) strerr_diefu2sys(111, "subscribe to events for ", argv[i]) ; - } - - for (i = 0 ; i < (unsigned int)argc ; i++) - { - s6_svstatus_t st = S6_SVSTATUS_ZERO ; - int isup ; - if (!s6_svstatus_read(argv[i], &st)) strerr_diefu1sys(111, "s6_svstatus_read") ; - isup = !!st.pid ; - if (re[0] == 'U' && isup) - { - unsigned int len = str_len(argv[i]) ; - char s[len + 1 + sizeof(S6_SUPERVISE_READY_FILENAME)] ; - byte_copy(s, len, argv[i]) ; - s[len] = '/' ; - byte_copy(s + len + 1, sizeof(S6_SUPERVISE_READY_FILENAME), S6_SUPERVISE_READY_FILENAME) ; - if (access(s, F_OK) < 0) - { - if (errno == ENOENT) isup = 0 ; - else strerr_warnwu2sys("check ", s) ; - } - } - bitarray_poke(states, i, isup) ; - } - - for (;;) - { - if (check(states, argc, wantup, or)) break ; - { - register int r = iopause_g(&x, 1, &deadline) ; - if (r < 0) strerr_diefu1sys(111, "iopause") ; - else if (!r) strerr_dief1x(1, "timed out") ; - } - - if (ftrigr_update(&a) < 0) strerr_diefu1sys(111, "ftrigr_update") ; - for (i = 0 ; i < (unsigned int)argc ; i++) - { - char what ; - register int r = ftrigr_check(&a, list[i], &what) ; - if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ; - if (r) bitarray_poke(states, i, what == re[0]) ; - } - } + s6_svlisten_t foo = S6_SVLISTEN_ZERO ; + uint16 ids[argc] ; + unsigned char upstate[bitarray_div8(argc)] ; + unsigned char readystate[bitarray_div8(argc)] ; + s6_svlisten_init(argc, argv, &foo, ids, upstate, readystate, &deadline) ; + return s6_svlisten_loop(&foo, wantup, wantready, or, &deadline, -1, 0) ; } - return 0 ; } diff --git a/src/supervision/s6_svlisten_loop.c b/src/supervision/s6_svlisten_loop.c new file mode 100644 index 0000000..00e911f --- /dev/null +++ b/src/supervision/s6_svlisten_loop.c @@ -0,0 +1,78 @@ +/* ISC license. */ + +#include <unistd.h> +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint16.h> +#include <skalibs/bitarray.h> +#include <skalibs/tai.h> +#include <skalibs/strerr2.h> +#include <skalibs/iopause.h> +#include <skalibs/djbunix.h> +#include <s6/ftrigr.h> +#include <s6/s6-supervise.h> +#include "s6-svlisten.h" + +void s6_svlisten_init (int argc, char const *const *argv, s6_svlisten_t *foo, uint16 *ids, unsigned char *upstate, unsigned char *readystate, tain_t const *deadline) +{ + register unsigned int i = 0 ; + foo->n = (unsigned int)argc ; + foo->ids = ids ; + foo->upstate = upstate ; + foo->readystate = readystate ; + if (!ftrigr_startf_g(&foo->a, deadline)) strerr_diefu1sys(111, "ftrigr_startf") ; + for (; i < foo->n ; i++) + { + s6_svstatus_t status = S6_SVSTATUS_ZERO ; + unsigned int len = str_len(argv[i]) ; + char s[len + 1 + sizeof(S6_SUPERVISE_EVENTDIR)] ; + byte_copy(s, len, argv[i]) ; + s[len] = '/' ; + byte_copy(s + len + 1, sizeof(S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR) ; + foo->ids[i] = ftrigr_subscribe_g(&foo->a, s, "D|u|U|d", FTRIGR_REPEAT, deadline) ; + if (!foo->ids[i]) strerr_diefu2sys(111, "subscribe to events for ", argv[i]) ; + if (!s6_svstatus_read(argv[i], &status)) strerr_diefu1sys(111, "s6_svstatus_read") ; + bitarray_poke(foo->upstate, i, status.pid && !status.flagfinishing) ; + bitarray_poke(foo->readystate, i, status.flagready) ; + } +} + +static inline int got (s6_svlisten_t const *foo, int wantup, int wantready, int or) +{ + register unsigned int m = bitarray_div8(foo->n) ; + unsigned char t[m] ; + byte_copy(t, m, foo->upstate) ; + if (!wantup) bitarray_not(t, 0, foo->n) ; + if (wantready) bitarray_and(t, t, foo->readystate, foo->n) ; + return (bitarray_first(t, foo->n, or) < foo->n) == or ; +} + +int s6_svlisten_loop (s6_svlisten_t *foo, int wantup, int wantready, int or, tain_t const *deadline, int spfd, action_func_t_ref handler) +{ + iopause_fd x[2] = { { .fd = ftrigr_fd(&foo->a), .events = IOPAUSE_READ }, { .fd = spfd, .events = IOPAUSE_READ, .revents = 0 } } ; + while (!got(foo, wantup, wantready, or)) + { + register int r = iopause_g(x, 1 + (spfd >= 0), deadline) ; + if (r < 0) strerr_diefu1sys(111, "iopause") ; + else if (!r) strerr_dief1x(1, "timed out") ; + if (x[1].revents & IOPAUSE_READ) (*handler)() ; + if (x[0].revents & IOPAUSE_READ) + { + register unsigned int i = 0 ; + if (ftrigr_update(&foo->a) < 0) strerr_diefu1sys(111, "ftrigr_update") ; + for (; i < foo->n ; i++) + { + char what ; + register int r = ftrigr_check(&foo->a, foo->ids[i], &what) ; + if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ; + if (r) + { + register unsigned int d = byte_chr("dDuU", 4, what) ; + bitarray_poke(foo->upstate, i, d & 2) ; + bitarray_poke(foo->readystate, i, d & 1) ; + } + } + } + } + return 0 ; +} diff --git a/src/supervision/s6_svlisten_signal_handler.c b/src/supervision/s6_svlisten_signal_handler.c new file mode 100644 index 0000000..0738f43 --- /dev/null +++ b/src/supervision/s6_svlisten_signal_handler.c @@ -0,0 +1,29 @@ +/* ISC license. */ + +#include <signal.h> +#include <skalibs/strerr2.h> +#include <skalibs/sig.h> +#include <skalibs/djbunix.h> +#include <skalibs/selfpipe.h> +#include "s6-svlisten.h" + +int s6_svlisten_selfpipe_init (void) +{ + register int spfd = selfpipe_init() ; + if (spfd < 0) strerr_diefu1sys(111, "selfpipe_init") ; + if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; + if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "ignore SIGPIPE") ; + return spfd ; +} + +void s6_svlisten_signal_handler (void) +{ + for (;;) switch (selfpipe_read()) + { + case -1 : strerr_diefu1sys(111, "selfpipe_read") ; + case 0 : return ; + case SIGCHLD : wait_reap() ; break ; + default : strerr_dief1x(101, "unexpected data in selfpipe") ; + } +} + |