summaryrefslogtreecommitdiff
path: root/src/supervision
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-07-20 20:20:54 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-07-20 20:20:54 +0000
commita3cdeecf0033919e3b5a79c17c19b5ac98719256 (patch)
tree92a930930f18a4f8ae897b1a69c39358137ce1e2 /src/supervision
parentbd34de9054cec794d96b0fde1eee9100e1d34215 (diff)
downloads6-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/supervision')
-rw-r--r--src/supervision/deps-exe/s6-notifywhenup3
-rw-r--r--src/supervision/deps-exe/s6-svlisten2
-rw-r--r--src/supervision/deps-exe/s6-svlisten12
-rw-r--r--src/supervision/deps-exe/s6-svwait1
-rw-r--r--src/supervision/s6-notifywhenup.c99
-rw-r--r--src/supervision/s6-supervise.c155
-rw-r--r--src/supervision/s6-svc.c27
-rw-r--r--src/supervision/s6-svlisten.c114
-rw-r--r--src/supervision/s6-svlisten.h29
-rw-r--r--src/supervision/s6-svlisten1.c102
-rw-r--r--src/supervision/s6-svscanctl.c12
-rw-r--r--src/supervision/s6-svstat.c31
-rw-r--r--src/supervision/s6-svwait.c92
-rw-r--r--src/supervision/s6_svlisten_loop.c78
-rw-r--r--src/supervision/s6_svlisten_signal_handler.c29
15 files changed, 291 insertions, 485 deletions
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") ;
+ }
+}
+