summaryrefslogtreecommitdiff
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
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
-rw-r--r--INSTALL2
-rw-r--r--doc/index.html6
-rw-r--r--doc/notifywhenup.html6
-rw-r--r--doc/s6-notifywhenup.html111
-rw-r--r--doc/s6-sudod.html13
-rw-r--r--doc/s6-supervise.html22
-rw-r--r--doc/s6-svc.html28
-rw-r--r--doc/s6-svlisten.html8
-rw-r--r--doc/s6-svlisten1.html5
-rw-r--r--doc/s6-svstat.html6
-rw-r--r--doc/s6-svwait.html10
-rw-r--r--doc/servicedir.html6
-rw-r--r--doc/upgrade.html21
-rw-r--r--package/deps.mak25
-rw-r--r--package/info2
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak1
-rw-r--r--src/include/s6/s6-supervise.h23
-rw-r--r--src/libs6/deps-lib/s61
-rw-r--r--src/libs6/s6_svc_writectl.c16
-rw-r--r--src/libs6/s6_svstatus_pack.c15
-rw-r--r--src/libs6/s6_svstatus_unpack.c37
-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
37 files changed, 454 insertions, 687 deletions
diff --git a/INSTALL b/INSTALL
index 684b138..97cf65a 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,7 +6,7 @@ Build Instructions
- A POSIX-compliant C development environment
- GNU make version 4.0 or later
- - skalibs version 2.3.5.1 or later: http://skarnet.org/software/skalibs/
+ - skalibs version 2.3.6.0 or later: http://skarnet.org/software/skalibs/
- execline version 2.1.2.2 or later: http://skarnet.org/software/execline/
This software will run on any operating system that implements
diff --git a/doc/index.html b/doc/index.html
index 87fe66b..0c23ff0 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -84,7 +84,7 @@ with s6</a> </li>
<li> GNU make, version 4.0 or later. Please be aware that s6 will not build
with an earlier version. </li>
<li> <a href="http://skarnet.org/software/skalibs/">skalibs</a> version
-2.3.5.1 or later. It's a build-time requirement. It's also a run-time
+2.3.6.0 or later. It's a build-time requirement. It's also a run-time
requirement if you link against the shared version of the skalibs
library. </li>
<li> <a href="http://skarnet.org/software/execline/">execline</a> version
@@ -101,7 +101,7 @@ library. </li>
<h3> Download </h3>
<ul>
- <li> The current released version of s6 is <a href="s6-2.1.6.0.tar.gz">2.1.6.0</a>. </li>
+ <li> The current released version of s6 is <a href="s6-2.2.0.0.tar.gz">2.2.0.0</a>. </li>
<li> Alternatively, you can checkout a copy of the s6 git repository:
<pre> git clone git://git.skarnet.org/s6 </pre> </li>
<li> There's also a
@@ -153,8 +153,6 @@ a user interface to control those processes and monitor service states.
<li><a href="s6-svwait.html">The <tt>s6-svwait</tt> program</a></li>
<li><a href="s6-svlisten1.html">The <tt>s6-svlisten1</tt> program</a></li>
<li><a href="s6-svlisten.html">The <tt>s6-svlisten</tt> program</a></li>
-<li><a href="s6-notifywhenup.html">The <tt>s6-notifywhenup</tt> program</a>
-<strong>(deprecated)</strong></li>
</ul>
<h4> Daemontools-like utilities </h4>
diff --git a/doc/notifywhenup.html b/doc/notifywhenup.html
index 9a288ac..6bc8b99 100644
--- a/doc/notifywhenup.html
+++ b/doc/notifywhenup.html
@@ -67,16 +67,16 @@ a generic mechanism that some daemons already implement.
<a href="servicedir.html">service directory</a> for the daemon contains
a valid <tt>notification-fd</tt> file, the daemon's supervisor, i.e. the
<a href="s6-supervise.html">s6-supervise</a> program, will properly catch
-the daemon's message, update a state file (<tt>supervise/ready</tt>), then
+the daemon's message, update the status file (<tt>supervise/status</tt>),
then notify all the subscribers
-with a 'U' event, meaning that the service is now up and ready.
+with a <tt>'U'</tt> event, meaning that the service is now up and ready.
</p>
<p>
This method should really be implemented in every long-running
program providing a service. When it is not the case, it's impossible
to provide reliable startup notifications, and subscribers should then
-be content with the unreliable 'u' events provided by s6-supervise.
+be content with the unreliable <tt>'u'</tt> events provided by s6-supervise.
</p>
</body>
diff --git a/doc/s6-notifywhenup.html b/doc/s6-notifywhenup.html
deleted file mode 100644
index cdfa693..0000000
--- a/doc/s6-notifywhenup.html
+++ /dev/null
@@ -1,111 +0,0 @@
-<html>
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <meta http-equiv="Content-Language" content="en" />
- <title>s6: the s6-notifywhenup program</title>
- <meta name="Description" content="s6: the s6-notifywhenup program" />
- <meta name="Keywords" content="s6 command s6-notifywhenup fifodir notification event notifier send service daemon ready" />
- <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
- </head>
-<body>
-
-<p>
-<a href="index.html">s6</a><br />
-<a href="http://skarnet.org/software/">Software</a><br />
-<a href="http://skarnet.org/">skarnet.org</a>
-</p>
-
-<h1> The s6-notifywhenup program </h1>
-
-<em>
-<p>
-Starting with s6-2.1.4.0, the s6-notifywhenup program has been deprecated,
-because there was still a case (albeit extremely rare) where a race
-condition would occur and readiness would be improperly advertised.
-Readiness notification for a service can now be achieved via a
-<tt>notification-fd</tt> file in the
-<a href="servicedir.html">service directory</a>, containing the
-number of the descriptor the service will write its readiness
-notification newline to. The notification will directly be picked by
-<a href="s6-supervise.html">s6-supervise</a>. <br />
-</p>
-
-<p>
- Quick upgrade recipe: for every service using s6-notifywhenup,
-replace the s6-notifywhenup invocation in your run script with
-<tt>fdmove 1 3</tt>, then perform <tt>echo 3 &gt; notification-fd</tt>.
-Done!
-</p>
-</em>
-
-<p>
-s6-notifywhenup launches a daemon while listening to a file descriptor,
-and sends a 'U' event to a <a href="fifodir.html">fifodir</a> when it
-receives something on that file descriptor.
-</p>
-
-<p>
-<a href="notifywhenup.html">This page</a> explains why this program is
-needed.
-</p>
-
-<h2> Interface </h2>
-
-<pre>
- s6-notifywhenup [ -d <em>fd</em> ] [ -e <em>fifodir</em> ] [ -f ] [ -X ] [ -t <em>timeout</em> ] <em>prog...</em>
-</pre>
-
-<ul>
- <li> s6-notifywhenup forks and executes <em>prog...</em> as the
-parent, with a pipe from <em>prog...</em>'s stdout to the child. </li>
- <li> The child waits for a newline (<tt>\n</tt>) to be written
-on the pipe. When it gets it, it creates a
-<tt>./supervise/ready</tt> file then sends a 'U' event to the
-<tt>./event</tt> fifodir. </li>
- <li> The child exits 0. </li>
-</ul>
-
-<h2> Options </h2>
-
-<ul>
- <li> <tt>-d&nbsp;<em>fd</em></tt>&nbsp;: listen to
-<em>prog</em>'s output on descriptor <em>fd</em>. The default is 1. </li>
- <li> <tt>-e&nbsp;<em>fifodir</em></tt>&nbsp;: send a 'U' event to fifodir
-<em>fifodir</em>. Default is <tt>./event</tt>. </li>
- <li> <tt>-f</tt>&nbsp;: simple fork. Normally, s6-notifywhenup doubleforks,
-in order to accommodate for a
-<em>prog</em> that does not expect to have a child and avoid a
-pending zombie. This option avoids the doublefork, but it should only be
-set if <em>prog</em> reaps even children it doesn't know it has. </li>
- <li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: if no EOF has been received
-after <em>timeout</em> milliseconds, exit without sending the event.
-Default is 0, meaning infinite. </li>
- <li> <tt>-X</tt>&nbsp;: fake readiness. s6-notifywhenup will actually send
-the newline itself before executing <em>prog</em>. This option should in
-principle never be used. </li>
-</ul>
-
-<h2> Notes </h2>
-
-<ul>
- <li> s6-notifywhenup executes <em>prog...</em> as the parent in order
-for <em>prog</em> to keep the same pid, which is vital for supervised
-processes. </li>
- <li> s6-notifywhenup can be used, for instance, with
-<a href="s6-ipcserver.html">s6-ipcserver</a>
-and its <tt>-1</tt> option, so that reliable startup notification is
-achieved. <tt>s6-notifywhenup -f s6-ipcserver -1 <em>args</em></tt> will
-send a 'U' event to <tt>./event</tt> when s6-ipcserver is actually
-listening to its socket. </li>
- <li> The <a href="s6-svwait.html">s6-svwait</a> program can be used
-to wait for 'U' events, as well as the
-<a href="s6-svlisten1.html">s6-svlisten1</a> and
-<a href="s6-svlisten.html">s6-svlisten</a> programs. </li>
- <li> The <tt>supervise/ready</tt> file, when created, contains at least
-the absolute time when s6-notifywhenup detected service readiness. The
-format and contents of this file are subject to change. </li>
-</ul>
-
-</body>
-</html>
diff --git a/doc/s6-sudod.html b/doc/s6-sudod.html
index 2c613da..54e9574 100644
--- a/doc/s6-sudod.html
+++ b/doc/s6-sudod.html
@@ -91,8 +91,8 @@ will set up a privileged program:
<pre>
#!/command/execlineb -P
fdmove -c 2 1
+fdmove 1 3
s6-envuidgid serveruser
-s6-notifywhenup -f
s6-ipcserver -U -1 -- serversocket
s6-ipcserver-access -v2 -l0 -i rules --
exec -c
@@ -106,12 +106,15 @@ sargv
executes the script. </li>
<li> <a href="http://skarnet.org/software/execline/fdmove.html">fdmove</a> makes
sure the script's error messages are sent to the service's logger. </li>
+ <li> <a href="http://skarnet.org/software/execline/fdmove.html">fdmove</a>
+redirects the script's stdout to file descriptor 3. This is useful if
+the service directory contains a <tt>notification-fd</tt> file containing
+<tt>3</tt>, so the daemon can perform
+<a href="notifywhenup.html">readiness notification</a> by writing a
+newline to its stdout. (The
+<tt>-1</tt> option to s6-ipcserver tells it to do this.) </li>
<li> <a href="s6-envuidgid.html">s6-envuidgid</a>
sets the UID, GID and GIDLIST environment variables for s6-ipcserver to interpret. </li>
- <li> <a href="s6-notifywhenup.html">s6-notifywhenup</a> primes the
-service for readiness notification (and the
-<tt>-1</tt> option to s6-ipcserver tells the daemon to actually
-notify when it's ready). </li>
<li> <a href="s6-ipcserver.html">s6-ipcserver</a> binds to <em>serversocket</em>,
drops its privileges to those of <em>serveruser</em>, and announces its
readiness. Then, for every client connecting to <em>serversocket</em>:
diff --git a/doc/s6-supervise.html b/doc/s6-supervise.html
index a16e0f5..081aeae 100644
--- a/doc/s6-supervise.html
+++ b/doc/s6-supervise.html
@@ -44,15 +44,18 @@ If it already exists, it uses it as is, without modifying the subscription right
<li> If the default service state is up, s6-supervise spawns <tt>./run</tt>. </li>
<li> s6-supervise sends a <tt>'u'</tt> event to <tt>./event</tt> whenever it
successfully spawns <tt>./run</tt>. </li>
- <li> When <tt>./run</tt> dies, s6-supervise sends a <tt>'d'</tt> event to <tt>./event</tt>. </li>
- <li> When <tt>./run</tt> dies, s6-supervise spawns <tt>./finish</tt> if it exists.
+ <li> When <tt>./run</tt> dies, s6-supervise sends a <tt>'d'</tt> event to <tt>./event</tt>.
+It then spawns <tt>./finish</tt> if it exists.
<tt>./finish</tt> will have <tt>./run</tt>'s exit code as first argument, or 256 if
<tt>./run</tt> was signaled; it will have the number of the signal that killed <tt>./run</tt>
as second argument, or an undefined number if <tt>./run</tt> was not signaled. </li>
- <li> <tt>./finish</tt> must exit in less than 5 seconds. If it takes more than that,
-s6-supervise kills it with a SIGKILL. </li>
- <li> When <tt>./finish</tt> dies, s6-supervise restarts <tt>./run</tt> unless it has been
-told not to. </li>
+ <li> By default, <tt>./finish</tt> must exit in less than 5 seconds. If it takes more than that,
+s6-supervise kills it with a SIGKILL. This can be configured via the
+<tt>./timeout-finish</tt> file, see the description in the
+<a href="servicedir.html">service directory page</a>. </li>
+ <li> When <tt>./finish</tt> dies (or is killed),
+s6-supervise sends a <tt>'D'</tt> event to <tt>./event</tt>. Then
+it restarts <tt>./run</tt> unless it has been told not to. </li>
<li> There is a minimum 1-second delay between two <tt>./run</tt> spawns, to avoid busylooping
if <tt>./run</tt> exits too quickly. </li>
<li> When killed or asked to exit, it waits for the service to go down one last time, then
@@ -78,10 +81,9 @@ what they do, are listed on the
<tt>notification-fd</tt> file when the service is started, or restarted,
s6-supervise creates and listens to an additional pipe from the service
for <a href="notifywhenup.html">readiness notification</a>. When the
-notification occurs, s6-supervise creates a <tt>./supervise/ready</tt>
-file containing the absolute time when readiness occurred, then sends
-a <tt>'U'</tt> event to <tt>./event</tt>. The <tt>./supervise/ready</tt>
-file is deleted on service death.
+notification occurs, s6-supervise updates the <tt>./supervise/status</tt>
+file accordingly, then sends
+a <tt>'U'</tt> event to <tt>./event</tt>.
</p>
<p>
diff --git a/doc/s6-svc.html b/doc/s6-svc.html
index 2de8ba4..f21847a 100644
--- a/doc/s6-svc.html
+++ b/doc/s6-svc.html
@@ -28,7 +28,7 @@ knowing their PIDs, and without using horrible hacks such as .pid files.
<h2> Interface </h2>
<pre>
- s6-svc [ -D | -U ] [ -T <em>timeout</em> ] [ -abqhkti12pcoduxO ] <em>servicedir</em>
+ s6-svc [ -wu | -wU | -wd | -wD ] [ -T <em>timeout</em> ] [ -abqhkti12pcoduxO ] <em>servicedir</em>
</pre>
<p>
@@ -75,13 +75,20 @@ it. </li>
(in milliseconds) after which s6-svc will exit 1 with an error message if
the service still hasn't reached the desired state. By default, the
timeout is 0, which means that s6-svc will block indefinitely. </li>
- <li> <tt>-D</tt>&nbsp;: s6-svc will not exit until the service is down. </li>
- <li> <tt>-U</tt>&nbsp;: s6-svc will not exit until the service is up and
+ <li> <tt>-wd</tt>&nbsp;: s6-svc will not exit until the service is down,
+i.e. until the <tt>run</tt> process has died. </li>
+ <li> <tt>-wD</tt>&nbsp;: s6-svc will not exit until the service is down
+<em>and</em> ready to be brought up, i.e. a possible <tt>finish</tt> script has
+exited. </li>
+ <li> <tt>-wu</tt>&nbsp;: s6-svc will not exit until the service is up,
+i.e. there is a process running the <tt>run</tt> executable. </li>
+ <li> <tt>-wU</tt>&nbsp;: s6-svc will not exit until the service is up <em>and</em>
<a href="notifywhenup.html">ready</a> as notified by the daemon itself.
If the <a href="servicedir.html">service directory</a> does not contain
a <tt>notification-fd</tt> file to tell
<a href="s6-supervise.html">s6-supervise</a> to accept readiness
-notification, s6-svc will print a warning and ignore the command. </li>
+notification, s6-svc will print a warning and act as if the <tt>-wu</tt>
+option had been given instead. </li>
</ul>
<h2> Usage examples </h2>
@@ -100,12 +107,13 @@ the process represented by the <tt>/service/sshd</tt> service directory -
typically the sshd server.
</p>
-<pre> s6-svc -Dd /service/ftpd </pre>
+<pre> s6-svc -wD -d /service/ftpd </pre>
<p>
- Take down the ftpd server and block until the process is really down.
+ Take down the ftpd server and block until the process is down and
+the finish script has completed.
</p>
-<pre> s6-svc -Uu -T 5000 /service/ftpd </pre>
+<pre> s6-svc -wU -T 5000 -u /service/ftpd </pre>
<p>
Bring up the ftpd server and block until it has sent notification that it
is ready. Exit 1 if it is still not ready after 5 seconds.
@@ -123,10 +131,10 @@ process is <a href="s6-log.html">s6-log</a>, this triggers a log rotation.
<li> s6-svc writes control commands into the <tt><em>servicedir</em>/supervise/control</tt>
FIFO. A s6-supervise process running on <em>servicedir</em> will be listening to this FIFO,
and will read and interpret those commands. </li>
- <li> When invoked with the <tt>-D</tt> or <tt>-U</tt> option, s6-svc executes into
+ <li> When invoked with one of the <tt>-w</tt> options, s6-svc executes into
<a href="s6-svlisten1.html">s6-svlisten1</a>, which will listen to service state
-changes and spawn another s6-svc instance (without the <tt>-D</tt> or <tt>-U</tt>
-option) that will send the commands to the service. Any error message written during
+changes and spawn another s6-svc instance (without the <tt>-w</tt> option)
+that will send the commands to the service. Any error message written during
the waiting period will mention it is being written by s6-svlisten1; this is normal. </li>
</ul>
diff --git a/doc/s6-svlisten.html b/doc/s6-svlisten.html
index 2316a2b..1db24c0 100644
--- a/doc/s6-svlisten.html
+++ b/doc/s6-svlisten.html
@@ -34,7 +34,7 @@ a collection of supervised services, and blocks until they all go up, or down.
</p>
<pre>
- s6-svlisten [ -U | -u | -d ] [ -a | -o ] [ -t <em>timeout</em> ] { <em>servicedir</em> <em>servicedir...</em> } <em>prog...</em>
+ s6-svlisten [ -U | -u | -D | -d ] [ -a | -o ] [ -t <em>timeout</em> ] { <em>servicedir</em> <em>servicedir...</em> } <em>prog...</em>
</pre>
<p>
@@ -42,7 +42,7 @@ a collection of supervised services, and blocks until they all go up, or down.
</p>
<pre>
- s6-svlisten [ -U | -u | -d ] [ -a | -o ] [ -t <em>timeout</em> ] <em>servicedir</em> <em>servicedir...</em> "" <em>prog...</em>
+ s6-svlisten [ -U | -u | -D | -d ] [ -a | -o ] [ -t <em>timeout</em> ] <em>servicedir</em> <em>servicedir...</em> "" <em>prog...</em>
</pre>
<ul>
@@ -69,6 +69,10 @@ specific support in the service programs, and the use of the
<a href="servicedir.html">service directory</a>.
See the explanation on <a href="notifywhenup.html">this page</a>. </li>
<li> <tt>-d</tt>&nbsp;: down. s6-svlisten will wait until the services are down. </li>
+ <li> <tt>-D</tt>&nbsp;: really down. s6-svlisten will wait until the
+services are down and the cleanup scripts in <tt><em>servicedir</em>/finish</tt>
+for every <em>servicedir</em>
+have finished executing (or have timed out and been killed). </li>
<li> <tt>-o</tt>&nbsp;: or. s6-svlisten will wait until <em>one</em> of the
given services comes up or down. </li>
<li> <tt>-a</tt>&nbsp;: and. s6-svlisten will wait until <em>all</em> of the
diff --git a/doc/s6-svlisten1.html b/doc/s6-svlisten1.html
index a9e147a..c3f5ef4 100644
--- a/doc/s6-svlisten1.html
+++ b/doc/s6-svlisten1.html
@@ -30,7 +30,7 @@ supervised service, and blocks until said service goes up, or down.
<h2> Interface </h2>
<pre>
- s6-svlisten [ -U | -u | -d ] [ -t <em>timeout</em> ] <em>servicedir</em> <em>prog...</em>
+ s6-svlisten [ -U | -u | -D | -d ] [ -t <em>timeout</em> ] <em>servicedir</em> <em>prog...</em>
</pre>
<ul>
@@ -57,6 +57,9 @@ specific support in the service programs, and the use of the
<a href="servicedir.html">service directory</a>.
See the explanation on <a href="notifywhenup.html">this page</a>. </li>
<li> <tt>-d</tt>&nbsp;: down. s6-svlisten1 will wait until the service is down. </li>
+ <li> <tt>-D</tt>&nbsp;: really down. s6-svlisten1 will wait until the
+service is down and the cleanup script in <tt><em>servicedir</em>/finish</tt>
+has finished executing (or has timed out and been killed). </li>
<li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: if the requested event has not
happened after <em>timeout</em> milliseconds, s6-svlisten1 will print a message
to stderr and exit 1. By default, <em>timeout</em> is 0, which means no time
diff --git a/doc/s6-svstat.html b/doc/s6-svstat.html
index e78c13f..5feef0f 100644
--- a/doc/s6-svstat.html
+++ b/doc/s6-svstat.html
@@ -46,7 +46,11 @@ signal, if it is down </li>
kernel's scheduler picks up s6-supervise </li>
<li> whether the service is <a href="notifywhenup.html">ready</a>,
as notified by the daemon itself, and
-if it is, the number of seconds that it has been. </li>
+if it is, the number of seconds that it has been.
+A service reported as down and ready simply means that it is ready
+to be brought up. A service is down and not ready when it is in the
+cleanup phase, i.e. the <tt>./finish</tt> script is still being executed. </li>
+ </li>
</ul>
<h2> Options </h2>
diff --git a/doc/s6-svwait.html b/doc/s6-svwait.html
index de209ea..c3df0fa 100644
--- a/doc/s6-svwait.html
+++ b/doc/s6-svwait.html
@@ -29,7 +29,7 @@ s6-svwait only waits for notifications; it never polls.
<h2> Interface </h2>
<pre>
- s6-svwait [ -U | -u | -d ] [ -a | -o ] [ -t <em>timeout</em> ] <em>servicedir...</em>
+ s6-svwait [ -U | -u | -D | -d ] [ -a | -o ] [ -t <em>timeout</em> ] <em>servicedir...</em>
</pre>
<p>
@@ -53,6 +53,11 @@ specific support in the service programs, and the use of the
<a href="servicedir.html">service directory</a>.
See the explanation on <a href="notifywhenup.html">this page</a>. </li>
<li> <tt>-d</tt>&nbsp;: down. s6-svwait will wait until the services are down. </li>
+ <li> <tt>-D</tt>&nbsp;: really down. s6-svwait will wait until the
+services are down and the cleanup scripts in
+<tt><em>servicedir</em>/finish</tt>
+for every <em>servicedir</em>
+have finished executing (or have timed out and been killed). </li>
<li> <tt>-o</tt>&nbsp;: or. s6-svwait will wait until <em>one</em> of the
given services comes up or down. </li>
<li> <tt>-a</tt>&nbsp;: and. s6-svwait will wait until <em>all</em> of the
@@ -80,8 +85,7 @@ s6-supervise has not been started yet. </li>
<p>
s6-svwait spawns a <a href="libs6/s6-ftrigrd.html">s6-ftrigrd</a> child to
listen to notifications sent by <a href="s6-supervise.html">s6-supervise</a>.
-It also checks <tt>supervise/status</tt> files, as well as the
-<tt>supervise/ready</tt> files if necessary, to get the current service
+It also checks <tt>supervise/status</tt> files to get the current service
states, so it is immune to race conditions.
</p>
diff --git a/doc/servicedir.html b/doc/servicedir.html
index 7cebd53..76a0a11 100644
--- a/doc/servicedir.html
+++ b/doc/servicedir.html
@@ -117,6 +117,12 @@ notification from the service and broadcast readiness, i.e. any
<a href="s6-svlisten1.html">s6-svlisten1 -U</a> or
<a href="s6-svlisten.html">s6-svlisten -U</a> processes will be
triggered. </li>
+ <li> An optional regular file named <tt>timeout-finish</tt>. If such a file
+exists, it must only contain an unsigned integer, which is the number of
+milliseconds after which the <tt>./finish</tt> script, if it exists, will
+be killed with a SIGKILL. The default is 5000: finish scripts are killed
+if they're still alive after 5 seconds. A value of 0 allows finish scripts
+to run forever. </li>
<li> A <a href="fifodir.html">fifodir</a> named <tt>event</tt>. It is automatically
created by <a href="s6-supervise.html">s6-supervise</a> if it does not exist.
<em>foo</em><tt>/event</tt>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index b6ae2c9..c77992b 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,6 +18,27 @@
<h1> What has changed in s6 </h1>
+<h2> in 2.2.0.0 </h2>
+
+<ul>
+ <li> skalibs dependency bumped to 2.3.6.0. </li>
+ <li> The internals of <a href="s6-supervise.html">s6-supervise</a> have
+changed; the <tt>supervise/status</tt> file ABI has changed and is not
+compatible with the daemontools/runit <tt>supervise/status</tt> files
+anymore. (This should not impact anything.) </li>
+ <li> <a href="s6-supervise.html">s6-supervise</a> features a
+configurable timeout for <tt>./finish</tt> scripts, via the
+<a href="servicedir.html"><tt>./timeout-finish</tt></a> file. </li>
+ <li> <a href="s6-svwait.html">s6-svwait</a>,
+<a href="s6-svlisten1.html">s6-svlisten1</a> and
+<a href="s6-svlisten.html">s6-svlisten</a> can now wait for a <tt>'D'</tt>
+event, which means the <tt>./finish</tt> script has terminated. </li>
+ <li> The deprecated <tt>s6-notifywhenup</tt> program has been
+removed. </li>
+ <li> The syntax for synchronous <a href="s6-svc.html">s6-svc</a>
+waiting has changed. </li>
+</ul>
+
<h2> in 2.1.6.0 </h2>
<ul>
diff --git a/package/deps.mak b/package/deps.mak
index d93bfb3..646205b 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -5,6 +5,7 @@
src/include/s6/ftrigr.h: src/include/s6/config.h
src/include/s6/s6.h: src/include/s6/accessrules.h src/include/s6/ftrigr.h src/include/s6/ftrigw.h src/include/s6/s6-supervise.h src/include/s6/s6lock.h
src/include/s6/s6lock.h: src/include/s6/config.h
+src/supervision/s6-svlisten.h: src/include/s6/ftrigr.h
src/conn-tools/s6-accessrules-cdb-from-fs.o src/conn-tools/s6-accessrules-cdb-from-fs.lo: src/conn-tools/s6-accessrules-cdb-from-fs.c
src/conn-tools/s6-accessrules-fs-from-cdb.o src/conn-tools/s6-accessrules-fs-from-cdb.lo: src/conn-tools/s6-accessrules-fs-from-cdb.c
src/conn-tools/s6-connlimit.o src/conn-tools/s6-connlimit.lo: src/conn-tools/s6-connlimit.c
@@ -30,6 +31,8 @@ src/daemontools-extras/s6-tai64n.o src/daemontools-extras/s6-tai64n.lo: src/daem
src/daemontools-extras/s6-tai64nlocal.o src/daemontools-extras/s6-tai64nlocal.lo: src/daemontools-extras/s6-tai64nlocal.c
src/daemontools-extras/ucspilogd.o src/daemontools-extras/ucspilogd.lo: src/daemontools-extras/ucspilogd.c
src/fdholder/s6-fdholder-daemon.o src/fdholder/s6-fdholder-daemon.lo: src/fdholder/s6-fdholder-daemon.c src/include/s6/config.h
+src/fdholder/s6-fdholder-delete.o src/fdholder/s6-fdholder-delete.lo: src/fdholder/s6-fdholder-delete.c src/include/s6/config.h
+src/fdholder/s6-fdholder-deletec.o src/fdholder/s6-fdholder-deletec.lo: src/fdholder/s6-fdholder-deletec.c src/include/s6/s6-fdholder.h
src/fdholder/s6-fdholder-getdump.o src/fdholder/s6-fdholder-getdump.lo: src/fdholder/s6-fdholder-getdump.c src/include/s6/config.h
src/fdholder/s6-fdholder-getdumpc.o src/fdholder/s6-fdholder-getdumpc.lo: src/fdholder/s6-fdholder-getdumpc.c src/include/s6/s6-fdholder.h
src/fdholder/s6-fdholder-list.o src/fdholder/s6-fdholder-list.lo: src/fdholder/s6-fdholder-list.c src/include/s6/config.h
@@ -86,6 +89,7 @@ src/libs6/s6_fdholder_store_async.o src/libs6/s6_fdholder_store_async.lo: src/li
src/libs6/s6_supervise_lock.o src/libs6/s6_supervise_lock.lo: src/libs6/s6_supervise_lock.c src/include/s6/s6-supervise.h
src/libs6/s6_supervise_lock_mode.o src/libs6/s6_supervise_lock_mode.lo: src/libs6/s6_supervise_lock_mode.c src/include/s6/s6-supervise.h
src/libs6/s6_svc_write.o src/libs6/s6_svc_write.lo: src/libs6/s6_svc_write.c src/include/s6/s6-supervise.h
+src/libs6/s6_svc_writectl.o src/libs6/s6_svc_writectl.lo: src/libs6/s6_svc_writectl.c src/include/s6/s6-supervise.h
src/libs6/s6_svstatus_pack.o src/libs6/s6_svstatus_pack.lo: src/libs6/s6_svstatus_pack.c src/include/s6/s6-supervise.h
src/libs6/s6_svstatus_read.o src/libs6/s6_svstatus_read.lo: src/libs6/s6_svstatus_read.c src/include/s6/s6-supervise.h
src/libs6/s6_svstatus_unpack.o src/libs6/s6_svstatus_unpack.lo: src/libs6/s6_svstatus_unpack.c src/include/s6/s6-supervise.h
@@ -108,16 +112,17 @@ src/pipe-tools/s6-ftrig-listen1.o src/pipe-tools/s6-ftrig-listen1.lo: src/pipe-t
src/pipe-tools/s6-ftrig-notify.o src/pipe-tools/s6-ftrig-notify.lo: src/pipe-tools/s6-ftrig-notify.c src/include/s6/ftrigw.h
src/pipe-tools/s6-ftrig-wait.o src/pipe-tools/s6-ftrig-wait.lo: src/pipe-tools/s6-ftrig-wait.c src/include/s6/ftrigr.h
src/pipe-tools/s6-mkfifodir.o src/pipe-tools/s6-mkfifodir.lo: src/pipe-tools/s6-mkfifodir.c src/include/s6/ftrigw.h
-src/supervision/s6-notifywhenup.o src/supervision/s6-notifywhenup.lo: src/supervision/s6-notifywhenup.c src/include/s6/ftrigw.h src/include/s6/s6-supervise.h
src/supervision/s6-supervise.o src/supervision/s6-supervise.lo: src/supervision/s6-supervise.c src/include/s6/ftrigw.h src/include/s6/s6-supervise.h
src/supervision/s6-svc.o src/supervision/s6-svc.lo: src/supervision/s6-svc.c src/include/s6/config.h src/include/s6/s6-supervise.h
-src/supervision/s6-svlisten.o src/supervision/s6-svlisten.lo: src/supervision/s6-svlisten.c src/include/s6/ftrigr.h src/include/s6/s6-supervise.h
-src/supervision/s6-svlisten1.o src/supervision/s6-svlisten1.lo: src/supervision/s6-svlisten1.c src/include/s6/ftrigr.h src/include/s6/s6-supervise.h
+src/supervision/s6-svlisten.o src/supervision/s6-svlisten.lo: src/supervision/s6-svlisten.c src/supervision/s6-svlisten.h
+src/supervision/s6-svlisten1.o src/supervision/s6-svlisten1.lo: src/supervision/s6-svlisten1.c src/supervision/s6-svlisten.h
src/supervision/s6-svok.o src/supervision/s6-svok.lo: src/supervision/s6-svok.c src/include/s6/s6-supervise.h
src/supervision/s6-svscan.o src/supervision/s6-svscan.lo: src/supervision/s6-svscan.c src/include/s6/config.h src/include/s6/s6-supervise.h
src/supervision/s6-svscanctl.o src/supervision/s6-svscanctl.lo: src/supervision/s6-svscanctl.c src/include/s6/s6-supervise.h
src/supervision/s6-svstat.o src/supervision/s6-svstat.lo: src/supervision/s6-svstat.c src/include/s6/s6-supervise.h
-src/supervision/s6-svwait.o src/supervision/s6-svwait.lo: src/supervision/s6-svwait.c src/include/s6/ftrigr.h src/include/s6/s6-supervise.h
+src/supervision/s6-svwait.o src/supervision/s6-svwait.lo: src/supervision/s6-svwait.c src/supervision/s6-svlisten.h
+src/supervision/s6_svlisten_loop.o src/supervision/s6_svlisten_loop.lo: src/supervision/s6_svlisten_loop.c src/supervision/s6-svlisten.h src/include/s6/ftrigr.h src/include/s6/s6-supervise.h
+src/supervision/s6_svlisten_signal_handler.o src/supervision/s6_svlisten_signal_handler.lo: src/supervision/s6_svlisten_signal_handler.c src/supervision/s6-svlisten.h
s6-accessrules-cdb-from-fs: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
s6-accessrules-cdb-from-fs: src/conn-tools/s6-accessrules-cdb-from-fs.o -lskarnet
@@ -199,8 +204,8 @@ s6-fdholder-transferdumpc: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
s6-fdholder-transferdumpc: src/fdholder/s6-fdholder-transferdumpc.o ${LIBS6} -lskarnet
s6-fdholderd: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
s6-fdholderd: src/fdholder/s6-fdholderd.o ${LIBS6} -lskarnet
-libs6.a: src/libs6/ftrigr1_zero.o src/libs6/ftrigr_check.o src/libs6/ftrigr_end.o src/libs6/ftrigr_start.o src/libs6/ftrigr_startf.o src/libs6/ftrigr_subscribe.o src/libs6/ftrigr_unsubscribe.o src/libs6/ftrigr_update.o src/libs6/ftrigr_wait_and.o src/libs6/ftrigr_wait_or.o src/libs6/ftrigr_zero.o src/libs6/ftrigw_clean.o src/libs6/ftrigw_fifodir_make.o src/libs6/ftrigw_notify.o src/libs6/ftrigw_notifyb.o src/libs6/ftrigw_notifyb_nosig.o src/libs6/s6_accessrules_backend_cdb.o src/libs6/s6_accessrules_backend_fs.o src/libs6/s6_accessrules_keycheck_ip4.o src/libs6/s6_accessrules_keycheck_ip6.o src/libs6/s6_accessrules_keycheck_reversedns.o src/libs6/s6_accessrules_keycheck_uidgid.o src/libs6/s6_accessrules_params_free.o src/libs6/s6_accessrules_uidgid_cdb.o src/libs6/s6_accessrules_uidgid_fs.o src/libs6/s6_supervise_lock.o src/libs6/s6_supervise_lock_mode.o src/libs6/s6_svc_write.o src/libs6/s6_svstatus_pack.o src/libs6/s6_svstatus_read.o src/libs6/s6_svstatus_unpack.o src/libs6/s6_svstatus_write.o src/libs6/s6lock_acquire.o src/libs6/s6lock_check.o src/libs6/s6lock_end.o src/libs6/s6lock_release.o src/libs6/s6lock_start.o src/libs6/s6lock_startf.o src/libs6/s6lock_update.o src/libs6/s6lock_wait_and.o src/libs6/s6lock_wait_or.o src/libs6/s6lock_zero.o src/libs6/s6_fdholder_delete.o src/libs6/s6_fdholder_delete_async.o src/libs6/s6_fdholder_getdump.o src/libs6/s6_fdholder_list.o src/libs6/s6_fdholder_list_async.o src/libs6/s6_fdholder_list_cb.o src/libs6/s6_fdholder_retrieve.o src/libs6/s6_fdholder_retrieve_async.o src/libs6/s6_fdholder_retrieve_cb.o src/libs6/s6_fdholder_setdump.o src/libs6/s6_fdholder_store.o src/libs6/s6_fdholder_store_async.o
-libs6.so: src/libs6/ftrigr1_zero.lo src/libs6/ftrigr_check.lo src/libs6/ftrigr_end.lo src/libs6/ftrigr_start.lo src/libs6/ftrigr_startf.lo src/libs6/ftrigr_subscribe.lo src/libs6/ftrigr_unsubscribe.lo src/libs6/ftrigr_update.lo src/libs6/ftrigr_wait_and.lo src/libs6/ftrigr_wait_or.lo src/libs6/ftrigr_zero.lo src/libs6/ftrigw_clean.lo src/libs6/ftrigw_fifodir_make.lo src/libs6/ftrigw_notify.lo src/libs6/ftrigw_notifyb.lo src/libs6/ftrigw_notifyb_nosig.lo src/libs6/s6_accessrules_backend_cdb.lo src/libs6/s6_accessrules_backend_fs.lo src/libs6/s6_accessrules_keycheck_ip4.lo src/libs6/s6_accessrules_keycheck_ip6.lo src/libs6/s6_accessrules_keycheck_reversedns.lo src/libs6/s6_accessrules_keycheck_uidgid.lo src/libs6/s6_accessrules_params_free.lo src/libs6/s6_accessrules_uidgid_cdb.lo src/libs6/s6_accessrules_uidgid_fs.lo src/libs6/s6_supervise_lock.lo src/libs6/s6_supervise_lock_mode.lo src/libs6/s6_svc_write.lo src/libs6/s6_svstatus_pack.lo src/libs6/s6_svstatus_read.lo src/libs6/s6_svstatus_unpack.lo src/libs6/s6_svstatus_write.lo src/libs6/s6lock_acquire.lo src/libs6/s6lock_check.lo src/libs6/s6lock_end.lo src/libs6/s6lock_release.lo src/libs6/s6lock_start.lo src/libs6/s6lock_startf.lo src/libs6/s6lock_update.lo src/libs6/s6lock_wait_and.lo src/libs6/s6lock_wait_or.lo src/libs6/s6lock_zero.lo src/libs6/s6_fdholder_delete.lo src/libs6/s6_fdholder_delete_async.lo src/libs6/s6_fdholder_getdump.lo src/libs6/s6_fdholder_list.lo src/libs6/s6_fdholder_list_async.lo src/libs6/s6_fdholder_list_cb.lo src/libs6/s6_fdholder_retrieve.lo src/libs6/s6_fdholder_retrieve_async.lo src/libs6/s6_fdholder_retrieve_cb.lo src/libs6/s6_fdholder_setdump.lo src/libs6/s6_fdholder_store.lo src/libs6/s6_fdholder_store_async.lo
+libs6.a: src/libs6/ftrigr1_zero.o src/libs6/ftrigr_check.o src/libs6/ftrigr_end.o src/libs6/ftrigr_start.o src/libs6/ftrigr_startf.o src/libs6/ftrigr_subscribe.o src/libs6/ftrigr_unsubscribe.o src/libs6/ftrigr_update.o src/libs6/ftrigr_wait_and.o src/libs6/ftrigr_wait_or.o src/libs6/ftrigr_zero.o src/libs6/ftrigw_clean.o src/libs6/ftrigw_fifodir_make.o src/libs6/ftrigw_notify.o src/libs6/ftrigw_notifyb.o src/libs6/ftrigw_notifyb_nosig.o src/libs6/s6_accessrules_backend_cdb.o src/libs6/s6_accessrules_backend_fs.o src/libs6/s6_accessrules_keycheck_ip4.o src/libs6/s6_accessrules_keycheck_ip6.o src/libs6/s6_accessrules_keycheck_reversedns.o src/libs6/s6_accessrules_keycheck_uidgid.o src/libs6/s6_accessrules_params_free.o src/libs6/s6_accessrules_uidgid_cdb.o src/libs6/s6_accessrules_uidgid_fs.o src/libs6/s6_supervise_lock.o src/libs6/s6_supervise_lock_mode.o src/libs6/s6_svc_write.o src/libs6/s6_svc_writectl.o src/libs6/s6_svstatus_pack.o src/libs6/s6_svstatus_read.o src/libs6/s6_svstatus_unpack.o src/libs6/s6_svstatus_write.o src/libs6/s6lock_acquire.o src/libs6/s6lock_check.o src/libs6/s6lock_end.o src/libs6/s6lock_release.o src/libs6/s6lock_start.o src/libs6/s6lock_startf.o src/libs6/s6lock_update.o src/libs6/s6lock_wait_and.o src/libs6/s6lock_wait_or.o src/libs6/s6lock_zero.o src/libs6/s6_fdholder_delete.o src/libs6/s6_fdholder_delete_async.o src/libs6/s6_fdholder_getdump.o src/libs6/s6_fdholder_list.o src/libs6/s6_fdholder_list_async.o src/libs6/s6_fdholder_list_cb.o src/libs6/s6_fdholder_retrieve.o src/libs6/s6_fdholder_retrieve_async.o src/libs6/s6_fdholder_retrieve_cb.o src/libs6/s6_fdholder_setdump.o src/libs6/s6_fdholder_store.o src/libs6/s6_fdholder_store_async.o
+libs6.so: src/libs6/ftrigr1_zero.lo src/libs6/ftrigr_check.lo src/libs6/ftrigr_end.lo src/libs6/ftrigr_start.lo src/libs6/ftrigr_startf.lo src/libs6/ftrigr_subscribe.lo src/libs6/ftrigr_unsubscribe.lo src/libs6/ftrigr_update.lo src/libs6/ftrigr_wait_and.lo src/libs6/ftrigr_wait_or.lo src/libs6/ftrigr_zero.lo src/libs6/ftrigw_clean.lo src/libs6/ftrigw_fifodir_make.lo src/libs6/ftrigw_notify.lo src/libs6/ftrigw_notifyb.lo src/libs6/ftrigw_notifyb_nosig.lo src/libs6/s6_accessrules_backend_cdb.lo src/libs6/s6_accessrules_backend_fs.lo src/libs6/s6_accessrules_keycheck_ip4.lo src/libs6/s6_accessrules_keycheck_ip6.lo src/libs6/s6_accessrules_keycheck_reversedns.lo src/libs6/s6_accessrules_keycheck_uidgid.lo src/libs6/s6_accessrules_params_free.lo src/libs6/s6_accessrules_uidgid_cdb.lo src/libs6/s6_accessrules_uidgid_fs.lo src/libs6/s6_supervise_lock.lo src/libs6/s6_supervise_lock_mode.lo src/libs6/s6_svc_write.lo src/libs6/s6_svc_writectl.lo src/libs6/s6_svstatus_pack.lo src/libs6/s6_svstatus_read.lo src/libs6/s6_svstatus_unpack.lo src/libs6/s6_svstatus_write.lo src/libs6/s6lock_acquire.lo src/libs6/s6lock_check.lo src/libs6/s6lock_end.lo src/libs6/s6lock_release.lo src/libs6/s6lock_start.lo src/libs6/s6lock_startf.lo src/libs6/s6lock_update.lo src/libs6/s6lock_wait_and.lo src/libs6/s6lock_wait_or.lo src/libs6/s6lock_zero.lo src/libs6/s6_fdholder_delete.lo src/libs6/s6_fdholder_delete_async.lo src/libs6/s6_fdholder_getdump.lo src/libs6/s6_fdholder_list.lo src/libs6/s6_fdholder_list_async.lo src/libs6/s6_fdholder_list_cb.lo src/libs6/s6_fdholder_retrieve.lo src/libs6/s6_fdholder_retrieve_async.lo src/libs6/s6_fdholder_retrieve_cb.lo src/libs6/s6_fdholder_setdump.lo src/libs6/s6_fdholder_store.lo src/libs6/s6_fdholder_store_async.lo
s6-ftrigrd: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
s6-ftrigrd: src/libs6/s6-ftrigrd.o src/libs6/ftrig1_free.o src/libs6/ftrig1_make.o -lskarnet
s6lockd: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
@@ -219,16 +224,14 @@ s6-ftrig-wait: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
s6-ftrig-wait: src/pipe-tools/s6-ftrig-wait.o ${LIBS6} -lskarnet
s6-mkfifodir: private EXTRA_LIBS :=
s6-mkfifodir: src/pipe-tools/s6-mkfifodir.o ${LIBS6} -lskarnet
-s6-notifywhenup: private EXTRA_LIBS := ${TAINNOW_LIB}
-s6-notifywhenup: src/supervision/s6-notifywhenup.o ${LIBS6} -lskarnet
s6-supervise: private EXTRA_LIBS := ${TAINNOW_LIB}
s6-supervise: src/supervision/s6-supervise.o ${LIBS6} -lskarnet
s6-svc: private EXTRA_LIBS :=
s6-svc: src/supervision/s6-svc.o ${LIBS6} -lskarnet
s6-svlisten: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
-s6-svlisten: src/supervision/s6-svlisten.o ${LIBS6} -lexecline -lskarnet
+s6-svlisten: src/supervision/s6-svlisten.o src/supervision/s6_svlisten_signal_handler.o src/supervision/s6_svlisten_loop.o ${LIBS6} -lexecline -lskarnet
s6-svlisten1: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
-s6-svlisten1: src/supervision/s6-svlisten1.o ${LIBS6} -lskarnet
+s6-svlisten1: src/supervision/s6-svlisten1.o src/supervision/s6_svlisten_signal_handler.o src/supervision/s6_svlisten_loop.o ${LIBS6} -lskarnet
s6-svok: private EXTRA_LIBS :=
s6-svok: src/supervision/s6-svok.o -lskarnet
s6-svscan: private EXTRA_LIBS := ${TAINNOW_LIB}
@@ -238,4 +241,4 @@ s6-svscanctl: src/supervision/s6-svscanctl.o ${LIBS6} -lskarnet
s6-svstat: private EXTRA_LIBS := ${SYSCLOCK_LIB}
s6-svstat: src/supervision/s6-svstat.o ${LIBS6} -lskarnet
s6-svwait: private EXTRA_LIBS := ${SOCKET_LIB} ${TAINNOW_LIB}
-s6-svwait: src/supervision/s6-svwait.o ${LIBS6} -lskarnet
+s6-svwait: src/supervision/s6-svwait.o src/supervision/s6_svlisten_loop.o ${LIBS6} -lskarnet
diff --git a/package/info b/package/info
index 596b02c..34b0446 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
package=s6
-version=2.1.6.0
+version=2.2.0.0
category=admin
package_macro_name=S6
diff --git a/package/modes b/package/modes
index 9692b1a..544b44c 100644
--- a/package/modes
+++ b/package/modes
@@ -8,7 +8,6 @@ s6lockd 0755
s6lockd-helper 0755
s6-cleanfifodir 0755
s6-mkfifodir 0755
-s6-notifywhenup 0755
s6-svscan 0755
s6-supervise 0755
s6-svc 0755
diff --git a/package/targets.mak b/package/targets.mak
index 277617a..f795431 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -8,7 +8,6 @@ s6-ftrig-wait \
s6lockd \
s6-cleanfifodir \
s6-mkfifodir \
-s6-notifywhenup \
s6-svscan \
s6-supervise \
s6-svc \
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") ;
+ }
+}
+