diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2018-03-21 18:00:10 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2018-03-21 18:00:10 +0000 |
commit | 75c4223a7f5a8a073ba0d898ef9d841fdaef2f63 (patch) | |
tree | d024c08659674117134314e67b4ff825ae51c1d9 /src/supervision | |
parent | 91eba4b27017c3b7bf0d0bb548a12a694ed51a3b (diff) | |
download | s6-75c4223a7f5a8a073ba0d898ef9d841fdaef2f63.tar.xz |
Add s6-svdt-clear, s6-permafailon
Diffstat (limited to 'src/supervision')
-rw-r--r-- | src/supervision/deps-exe/s6-permafailon | 2 | ||||
-rw-r--r-- | src/supervision/deps-exe/s6-svdt-clear | 2 | ||||
-rw-r--r-- | src/supervision/s6-permafailon.c | 118 | ||||
-rw-r--r-- | src/supervision/s6-svdt-clear.c | 15 |
4 files changed, 137 insertions, 0 deletions
diff --git a/src/supervision/deps-exe/s6-permafailon b/src/supervision/deps-exe/s6-permafailon new file mode 100644 index 0000000..08815d9 --- /dev/null +++ b/src/supervision/deps-exe/s6-permafailon @@ -0,0 +1,2 @@ +${LIBS6} +-lskarnet diff --git a/src/supervision/deps-exe/s6-svdt-clear b/src/supervision/deps-exe/s6-svdt-clear new file mode 100644 index 0000000..08815d9 --- /dev/null +++ b/src/supervision/deps-exe/s6-svdt-clear @@ -0,0 +1,2 @@ +${LIBS6} +-lskarnet diff --git a/src/supervision/s6-permafailon.c b/src/supervision/s6-permafailon.c new file mode 100644 index 0000000..db9ccb6 --- /dev/null +++ b/src/supervision/s6-permafailon.c @@ -0,0 +1,118 @@ +/* ISC license. */ + +#include <sys/stat.h> +#include <string.h> +#include <signal.h> +#include <skalibs/types.h> +#include <skalibs/strerr2.h> +#include <skalibs/bitarray.h> +#include <skalibs/sig.h> +#include <skalibs/tai.h> +#include <skalibs/djbunix.h> +#include <s6/s6-supervise.h> + +#define USAGE "s6-permafailon seconds deathcount statuslist prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +static void list_scan (char const *s, unsigned char *codes, sigset_t *sigs) +{ + size_t pos = 0 ; + while (s[pos]) + { + unsigned int u ; + size_t len = uint_scan(s + pos, &u) ; + if (len) + { + if (u > 255) strerr_dief1x(100, "invalid exit code") ; + pos += len ; + if (s[pos] == '-') + { + unsigned int v ; + pos++ ; + len = uint_scan(s + pos, &v) ; + if (!len) strerr_dief1x(100, "invalid interval specification") ; + if (v > 255) strerr_dief1x(100, "invalid exit code") ; + if (v < u) strerr_dief1x(100, "invalid interval") ; + pos += len ; + bitarray_setn(codes, u, v - u + 1) ; + } + else bitarray_set(codes, u) ; + } + else + { + int sig ; + size_t next = pos ; + while (!strchr(",; \n\r\t", s[next])) next++ ; + char tmp[next - pos + 1] ; + memcpy(tmp, s + pos, next - pos) ; + tmp[next - pos] = 0 ; + len = sig0_scan(tmp, &sig) ; + if (!len) strerr_dief1x(100, "invalid status list specification") ; + pos += len ; + if (sigaddset(sigs, sig) < 0) strerr_dief1x(100, "invalid signal") ; + } + while (memchr(",; \n\r\t", s[pos], 6)) pos++ ; + } +} + +int main (int argc, char const *const *argv, char const *const *envp) +{ + unsigned char codes[32] ; + sigset_t sigs ; + unsigned int total, seconds, n ; + struct stat st ; + PROG = "s6-permafailon" ; + if (argc < 4) dieusage() ; + + if (!uint0_scan(argv[1], &seconds)) dieusage() ; + if (!uint0_scan(argv[2], &n)) dieusage() ; + if (!n) dieusage() ; + if (n > S6_MAX_DEATH_TALLY) n = S6_MAX_DEATH_TALLY ; + list_scan(argv[3], codes, &sigs) ; + + if (stat(S6_DTALLY_FILENAME, &st) < 0) + { + strerr_warnwu2sys("stat ", S6_DTALLY_FILENAME) ; + goto cont ; + } + if (st.st_size % S6_DTALLY_PACK || st.st_size > S6_DTALLY_PACK * S6_MAX_DEATH_TALLY) + { + strerr_warnw2x("invalid ", S6_DTALLY_FILENAME) ; + goto cont ; + } + total = st.st_size / S6_DTALLY_PACK ; + { + tain_t mintime ; + unsigned int matches = 0 ; + s6_dtally_t tab[total] ; + ssize_t r = s6_dtally_read(".", tab, total) ; + if (r <= 0) + { + if (r < 0) strerr_warnwu2sys("read ", S6_DTALLY_FILENAME) ; + goto cont ; + } + if (r < n) goto cont ; + tain_uint(&mintime, seconds) ; + tain_sub(&mintime, &tab[r-1].stamp, &mintime) ; + + for (unsigned int i = 0 ; i < r ; i++) + { + if (!tain_less(&tab[i].stamp, &mintime) + && ((tab[i].sig && sigismember(&sigs, tab[i].sig)) || bitarray_peek(codes, tab[i].exitcode)) + && ++matches >= n) + { + char fmtevent[4] ; + char fmtseconds[UINT_FMT] ; + char fmtn[UINT_FMT] ; + fmtevent[uint_fmt(fmtevent, tab[i].sig ? tab[i].sig : tab[i].exitcode)] = 0 ; + fmtseconds[uint_fmt(fmtseconds, seconds)] = 0 ; + fmtn[uint_fmt(fmtseconds, n)] = 0 ; + strerr_warni8x("PERMANENT FAILURE triggered after ", fmtn, " events involving ", tab[i].sig ? "signal " : "exit code ", fmtevent, " in the last ", fmtseconds, " seconds") ; + return 125 ; + } + } + } + + cont: + xpathexec0_run(argv + 4, envp) ; +} diff --git a/src/supervision/s6-svdt-clear.c b/src/supervision/s6-svdt-clear.c new file mode 100644 index 0000000..4db4858 --- /dev/null +++ b/src/supervision/s6-svdt-clear.c @@ -0,0 +1,15 @@ +/* ISC license. */ + +#include <skalibs/strerr2.h> +#include <s6/s6-supervise.h> + +#define USAGE "s6-svdt-clear servicedir" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv) +{ + if (argc < 1) dieusage() ; + if (!s6_dtally_write(argv[1], 0, 0)) + strerr_diefu2sys(111, "clear death tally for service ", argv[1]) ; + return 0 ; +} |