summaryrefslogtreecommitdiff
path: root/src/supervision
diff options
context:
space:
mode:
Diffstat (limited to 'src/supervision')
-rw-r--r--src/supervision/s6-supervise.c30
-rw-r--r--src/supervision/s6-svscan.c7
-rw-r--r--src/supervision/s6-svscanctl.c55
-rw-r--r--src/supervision/s6-svstat.c48
4 files changed, 114 insertions, 26 deletions
diff --git a/src/supervision/s6-supervise.c b/src/supervision/s6-supervise.c
index 65cbd9d..bb4e761 100644
--- a/src/supervision/s6-supervise.c
+++ b/src/supervision/s6-supervise.c
@@ -45,7 +45,7 @@ typedef void action_t (void) ;
typedef action_t *action_t_ref ;
static tain_t deadline ;
-static s6_svstatus_t status = { .stamp = TAIN_ZERO, .pid = 0, .flagwant = 1, .flagwantup = 1, .flagpaused = 0, .flagfinishing = 0 } ;
+static s6_svstatus_t status = { .stamp = TAIN_ZERO, .pid = 0, .flagwant = 1, .flagwantup = 1, .flagpaused = 0, .flagfinishing = 0, .wstat = 0 } ;
static state_t state = DOWN ;
static int flagsetsid = 1 ;
static int cont = 1 ;
@@ -166,7 +166,7 @@ static void trystart (void)
if (flagsetsid) setsid() ;
execve("./run", (char *const *)cargv, (char *const *)environ) ;
fd_write(p[1], "", 1) ;
- strerr_dieexec(111, "run") ;
+ strerr_dieexec(127, "run") ;
}
fd_close(p[1]) ;
{
@@ -194,7 +194,7 @@ static void trystart (void)
status.pid = pid ;
tain_copynow(&status.stamp) ;
announce() ;
- ftrigw_notify(S6_SUPERVISE_EVENTDIR, 'u') ;
+ ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "u", 1) ;
}
static void downtimeout (void)
@@ -230,7 +230,7 @@ static void down_d (void)
announce() ;
}
-static void tryfinish (int wstat, int islast)
+static inline void tryfinish (int islast)
{
register pid_t pid = fork() ;
if (pid < 0)
@@ -238,7 +238,6 @@ static void tryfinish (int wstat, int islast)
strerr_warnwu2sys("fork for ", "./finish") ;
if (islast) bail() ;
state = DOWN ;
- status.pid = 0 ;
settimeout(1) ;
return ;
}
@@ -248,16 +247,15 @@ static void tryfinish (int wstat, int islast)
char fmt1[UINT_FMT] ;
char *cargv[4] = { "finish", fmt0, fmt1, 0 } ;
selfpipe_finish() ;
- fmt0[uint_fmt(fmt0, WIFSIGNALED(wstat) ? 255 : WEXITSTATUS(wstat))] = 0 ;
- fmt1[uint_fmt(fmt1, WTERMSIG(wstat))] = 0 ;
+ fmt0[uint_fmt(fmt0, WIFSIGNALED(status.wstat) ? 256 : WEXITSTATUS(status.wstat))] = 0 ;
+ fmt1[uint_fmt(fmt1, WTERMSIG(status.wstat))] = 0 ;
if (flagsetsid) setsid() ;
execve("./finish", cargv, (char *const *)environ) ;
- _exit(111) ;
+ _exit(127) ;
}
status.pid = pid ;
status.flagfinishing = 1 ;
state = islast ? LASTFINISH : FINISH ;
- settimeout(5) ;
}
static void uptimeout (void)
@@ -268,18 +266,20 @@ static void uptimeout (void)
static void uplastup_z (int islast)
{
- int wstat = status.pid ;
+ status.wstat = status.pid ;
status.pid = 0 ;
tain_copynow(&status.stamp) ;
+ tryfinish(islast) ;
announce() ;
- ftrigw_notify(S6_SUPERVISE_EVENTDIR, 'd') ;
+ ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "d", 1) ;
if (unlink(S6_SUPERVISE_READY_FILENAME) < 0 && errno != ENOENT)
strerr_warnwu1sys("unlink " S6_SUPERVISE_READY_FILENAME) ;
- tryfinish(wstat, islast) ;
+ settimeout(5) ;
}
static void up_z (void)
{
+ status.flagpaused = 0 ;
uplastup_z(0) ;
}
@@ -401,7 +401,7 @@ static void handle_signals (void)
if (errno != ECHILD) strerr_diefu1sys(111, "wait_pid_nohang") ;
else break ;
else if (!r) break ;
- status.pid = wstat ;
+ status.pid = wstat ; /* don't overwrite status.wstat if it's ./finish */
(*actions[state][V_CHLD])() ;
}
break ;
@@ -490,7 +490,7 @@ int main (int argc, char const *const *argv)
settimeout(0) ;
tain_copynow(&status.stamp) ;
announce() ;
- ftrigw_notify(S6_SUPERVISE_EVENTDIR, 's') ;
+ ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "s", 1) ;
while (cont)
{
@@ -506,7 +506,7 @@ int main (int argc, char const *const *argv)
}
}
- ftrigw_notify(S6_SUPERVISE_EVENTDIR, 'x') ;
+ ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "x", 1) ;
}
return 0 ;
}
diff --git a/src/supervision/s6-svscan.c b/src/supervision/s6-svscan.c
index 8b0f82e..e07ff35 100644
--- a/src/supervision/s6-svscan.c
+++ b/src/supervision/s6-svscan.c
@@ -29,7 +29,7 @@
#define DIR_RETRY_TIMEOUT 3
#define CHECK_RETRY_TIMEOUT 4
-struct svinfo
+struct svinfo_s
{
dev_t dev ;
ino_t ino ;
@@ -39,9 +39,8 @@ struct svinfo
unsigned int flagactive : 1 ;
unsigned int flaglog : 1 ;
} ;
-#define SVINFO_ZERO { -1, -1, { TAIN_ZERO, TAIN_ZERO }, { 0, 0 }, { -1, -1 }, 0, 0, 0 } ;
-static struct svinfo *services ;
+static struct svinfo_s *services ;
static unsigned int max = 500 ;
static unsigned int n = 0 ;
static tain_t deadline, defaulttimeout ;
@@ -452,7 +451,7 @@ int main (int argc, char const *const *argv)
{
- struct svinfo blob[max] ; /* careful with that stack, Eugene */
+ struct svinfo_s blob[max] ; /* careful with that stack, Eugene */
services = blob ;
tain_now_g() ;
diff --git a/src/supervision/s6-svscanctl.c b/src/supervision/s6-svscanctl.c
index 48e6420..6529e9c 100644
--- a/src/supervision/s6-svscanctl.c
+++ b/src/supervision/s6-svscanctl.c
@@ -1,12 +1,65 @@
/* ISC license. */
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
#include <skalibs/strerr2.h>
#include <s6/s6-supervise.h>
#define USAGE "s6-svscanctl [ -phratszbnNiq0678 ] svscandir"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+#define DATASIZE 64
int main (int argc, char const *const *argv)
{
+ char data[DATASIZE] ;
+ unsigned int datalen = 0 ;
+ int r ;
PROG = "s6-svscanctl" ;
- return s6_svc_main(argc, argv, "phratszbnNiq0678", USAGE, ".s6-svscan") ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "phratszbnNiq0678", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'p' :
+ case 'h' :
+ case 'r' :
+ case 'a' :
+ case 't' :
+ case 's' :
+ case 'z' :
+ case 'b' :
+ case 'n' :
+ case 'N' :
+ case 'i' :
+ case 'q' :
+ case '0' :
+ case '6' :
+ case '7' :
+ case '8' :
+ {
+ if (datalen >= DATASIZE) strerr_dief1x(100, "too many commands") ;
+ data[datalen++] = opt ;
+ break ;
+ }
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ 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") ;
+ return 0 ;
}
diff --git a/src/supervision/s6-svstat.c b/src/supervision/s6-svstat.c
index c986b8d..a4facf5 100644
--- a/src/supervision/s6-svstat.c
+++ b/src/supervision/s6-svstat.c
@@ -1,27 +1,46 @@
/* ISC license. */
-#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
#include <skalibs/uint64.h>
#include <skalibs/uint.h>
#include <skalibs/bytestr.h>
#include <skalibs/buffer.h>
#include <skalibs/strerr2.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/sig.h>
#include <skalibs/tai.h>
#include <skalibs/djbunix.h>
#include <s6/s6-supervise.h>
-#define USAGE "s6-svstat servicedir"
+#define USAGE "s6-svstat [ -n ] servicedir"
+#define dieusage() strerr_dieusage(100, USAGE)
int main (int argc, char const *const *argv)
{
s6_svstatus_t status ;
- char fmt[UINT_FMT] ;
+ int flagnum = 0 ;
int isup, normallyup ;
+ char fmt[UINT_FMT] ;
PROG = "s6-svstat" ;
- if (argc < 2) strerr_dieusage(100, USAGE) ;
- argv++ ; argc-- ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "n", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : flagnum = 1 ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) dieusage() ;
+
if (!s6_svstatus_read(*argv, &status))
strerr_diefu2sys(111, "read status for ", *argv) ;
@@ -48,7 +67,24 @@ int main (int argc, char const *const *argv)
buffer_putnoflush(buffer_1small, fmt, uint_fmt(fmt, status.pid)) ;
buffer_putnoflush(buffer_1small, ") ", 2) ;
}
- else buffer_putnoflush(buffer_1small, "down ", 5) ;
+ else
+ {
+ buffer_putnoflush(buffer_1small, "down (", 6) ;
+ if (WIFSIGNALED(status.wstat))
+ {
+ buffer_putnoflush(buffer_1small, "signal ", 7) ;
+ if (flagnum)
+ buffer_putnoflush(buffer_1small, fmt, uint_fmt(fmt, WTERMSIG(status.wstat))) ;
+ else
+ buffer_putsnoflush(buffer_1small, sig_name(WTERMSIG(status.wstat))) ;
+ }
+ else
+ {
+ buffer_putnoflush(buffer_1small, "exitcode ", 9) ;
+ buffer_putnoflush(buffer_1small, fmt, uint_fmt(fmt, WEXITSTATUS(status.wstat))) ;
+ }
+ buffer_putnoflush(buffer_1small, ") ", 2) ;
+ }
buffer_putnoflush(buffer_1small, fmt, uint64_fmt(fmt, status.stamp.sec.x)) ;
buffer_putnoflush(buffer_1small," seconds", 8) ;