summaryrefslogtreecommitdiff
path: root/src/supervision/s6-supervise.c
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/s6-supervise.c
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/s6-supervise.c')
-rw-r--r--src/supervision/s6-supervise.c155
1 files changed, 79 insertions, 76 deletions
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 ;