summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/faq.html129
-rw-r--r--doc/index.html5
-rw-r--r--doc/overview.html7
-rw-r--r--doc/s6-rc-bundle.html4
-rw-r--r--doc/s6-rc-compile.html25
-rw-r--r--doc/s6-rc-dryrun.html3
-rw-r--r--doc/s6-rc-init.html24
-rw-r--r--doc/s6-rc-oneshot-run.html4
-rw-r--r--doc/s6-rc-update.html26
-rw-r--r--doc/s6-rc.html21
-rw-r--r--doc/why.html42
-rw-r--r--src/s6-rc/s6-rc-update.c10
12 files changed, 215 insertions, 85 deletions
diff --git a/doc/faq.html b/doc/faq.html
index 692c7f7..608c5e2 100644
--- a/doc/faq.html
+++ b/doc/faq.html
@@ -16,13 +16,62 @@
<a href="http://skarnet.org/">skarnet.org</a>
</p>
-<h1> s6-rc: FAQ </h1>
+<h1> s6-rc: Frequently Asked Questions </h1>
+
+<h2> Quick recipes </h2>
+
+<h3> How do I... </h3>
+
+<h4> list every active service&nbsp;? </h4>
+
+<pre>s6-rc -a list </pre>
+
+<h4> list every service in the current live database, active or not&nbsp;? </h4>
+
+<pre>s6-rc -d list </pre>
+<p>or</p>
+<pre>s6-rc-db list services</pre>
+
+<h4> bring up service <em>foo</em>&nbsp;? </h4>
+
+<pre>s6-rc -u change foo</pre>
+
+<h4> bring down everything&nbsp;? </h4>
+
+<pre>s6-rc -da change</pre>
+
+<h4> print the "up" script for oneshot service <em>foo</em>&nbsp;? </h4>
+
+<pre>s6-rc-db -u script foo | xargs -0 printf "%s "</pre>
+
+<h4> see what pipeline longrun service <em>foo</em> is a part of&nbsp;? </h4>
+
+<pre>s6-rc-db pipeline foo</pre>
+
+<h4> see the list of all services that depend on <em>foo</em>,
+directly or indirectly&nbsp;? </h4>
+
+<pre>s6-rc-db -d all-dependencies foo</pre>
+
+<h4> see what services will restart if I update my live service database to
+<em>newcompiled</em>&nbsp;? </h4>
+
+<pre>s6-rc-update -n newcompiled</pre>
+
+<p>
+ The first line is the <a href="s6-rc.html">s6-rc</a> invocation that
+will bring the old services down. The services that will stop are listed
+after <tt>-- change</tt>.
+ The second line is the <a href="s6-rc.html">s6-rc</a> invocation that
+will bring the new services up. The services that will start are listed
+after <tt>-- change</tt>.
+</p>
<h2> The s6-rc-compile source format </h2>
<h3> The source format for
<a href="s6-rc-compile.html">s6-rc-compile</a> is not very convenient.
-Why not put all the information for a service in a single file? </h3>
+Why not put all the information for a service in a single file&nbsp;? </h3>
<p>
Because parsing sucks. Writing parsers is an annoying, ungrateful task,
@@ -37,16 +86,17 @@ file.
<p>
Using the filesystem as a key-value store is
a good technique to avoid parsing, and skarnet.org packages do it
-everywhere: for instance, look at
-<a href="http://skarnet.org/software/s6/s6-envdir.html">s6-envdir</a>.
+everywhere: for instance,
+<a href="http://skarnet.org/software/s6/s6-envdir.html">s6-envdir</a>
+uses the file name as a key and the file contents as a value.
The s6-rc-compile source format is just another instance of this
technique.
</p>
<p>
- This format generally plays well with automated tools, be it for
+ The source format generally plays well with automated tools, be it for
reading, as s6-rc-compile does, as for writing.
-I fully expect the s6-rc-compile source format
+I fully expect it
to be used as the input (resp. the output) of some automated tools that
would convert
service definitions to (resp. from) another format, such as systemd
@@ -55,17 +105,19 @@ s6-rc source format will make it easy on those tools.
</p>
<p>
- And if you love configuration files, don't mind writing a parser (which is
+ And if you love configuration files, are ok with writing a parser (which is
indubitably easier to do in other languages than C), and want to write
a program that takes a text file, parses it and outputs a service
-definition directory, it should also be rather easy.
+definition directory in the s6-rc-compile source format, it should also be
+rather easy - please, feel free!
</p>
<h3> There are no "Provides:", no virtual services. What do I do
-if I have several implementations for a service? </h3>
+if I have several implementations for a service&nbsp;? </h3>
<p>
- Use bundles. Bundles are awesome.
+ Use bundles. Bundles are the solution to most of the questions in
+the same vein.
</p>
<p>
@@ -84,7 +136,7 @@ will resolve to <em>opensshd</em>, and the compiled service database
will consider <em>opensshd</em> to be the "real" service; but users
will still be able to run
<a href="s6-rc.html">s6-rc</a> commands involving <em>sshd</em>.
-And if users want to change the default to <em>dropbear</em>, just
+And if you want to change the default to <em>dropbear</em>, just
change the <em>sshd</em><tt>/contents</tt> file to <tt>dropbear</tt>,
recompile the database, and
run <a href="s6-rc-update.html">s6-rc-update</a>.
@@ -113,7 +165,7 @@ one of them.
<h3> I have a collection of init scripts in another format,
but don't want to wait until the whole collection is converted
-before switching to s6-rc. Is there a smooth way in? </h3>
+before switching to s6-rc. Is there a smooth way in&nbsp;? </h3>
<p>
Yes.
@@ -163,7 +215,7 @@ you fix it.
<h3> There are no runlevels in s6-rc. I like runlevels. </h3>
<p>
- You have better than runlevels. <em>You have bundles.</em>
+ You have better than runlevels. You have bundles.
</p>
<p>
@@ -209,11 +261,57 @@ for.
When in doubt, use bundles.
</p>
+<h3> There are no intermediate states in s6-rc. There's just "up"
+and "down", no "starting", no "failed", etc. Why&nbsp;? </h3>
+
+<p>
+ Because those intermediate states are unnecessary.
+</p>
+
+<p>
+ From the machine's point of view, things are simple: a service is
+either up or it's not. If a service fails to start, then it's still
+down. Note that it is recommended to write <em>atomic</em> oneshots
+for this very reason.
+</p>
+
+<p>
+ Service managers that use intermediate states do so in order to keep
+track of what they're doing and what they have done. But this
+introduces needless complexity: the reality is that the service is
+either up or down, it's either in the state you wanted it to be or
+not. A model should not be more complex than the reality.
+</p>
+
+<p>
+ s6-rc does not keep track of "failed" states: a service that fails
+to start simply remains down, and
+<a href="s6-rc.html">s6-rc</a> exits 1 to report that something
+went wrong. To know what services failed to start, compare the
+result of <tt>s6-rc -a list</tt> against your expected machine state.
+</p>
+
+<p>
+ The reason for this design is simple: if the
+<a href="s6-rc.html">s6-rc</a> process is killed in the middle of a transition
+while a service state is "starting", what should the next invocation do?
+This is unclear, and the intermediate state introduces ambiguity where
+there should not be. Also,
+if there is a "failed" service, what should the next invocation do? Try
+and restart it, or not? This depends on what the user wants; this is
+policy, not mechanism. Simply reporting the error while keeping the
+state as "down" allows users to apply their chosen policies - see below.
+</p>
+
+<p>
+ Keep it simple, stupid.
+</p>
+
<h2> Mechanism vs. policy </h2>
<h3> s6-rc feels bare: there are tools, but no wrappers, no pre-packaged
scripts to boot my machines, no default runlevels. By comparison, OpenRC
-provides a complete default set of scripts! </h3>
+provides a complete default set of scripts&nbsp;! </h3>
<p>
In the world of software development, it is important to distinguish
@@ -248,7 +346,8 @@ distributors' job!
<em>for</em> a Linux distribution, so with that in mind, the OpenRC
developers did not have to think much about separating mechanism from policy.
It works very well for Gentoo and Gentoo-derived distributions; but it
-requires more work to use OpenRC outside of that frame.
+requires adaptation and more work for the admin to use OpenRC outside of
+that frame.
</p>
</body>
diff --git a/doc/index.html b/doc/index.html
index 58e60e3..ecb1fe4 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -107,6 +107,11 @@ the previous versions of s6-rc and the current one. </li>
<li> <a href="s6-rc-init.html">The <tt>s6-rc-init</tt> program</a> </li>
<li> <a href="s6-rc.html">The <tt>s6-rc</tt> program</a> </li>
<li> <a href="s6-rc-update.html">The <tt>s6-rc-update</tt> program</a> </li>
+</ul>
+
+<h4> Programs used internally </h4>
+
+<ul>
<li> <a href="s6-rc-dryrun.html">The <tt>s6-rc-dryrun</tt> internal program</a> </li>
<li> <a href="s6-rc-oneshot-run.html">The <tt>s6-rc-oneshot-run</tt> internal program</a> </li>
</ul>
diff --git a/doc/overview.html b/doc/overview.html
index 0d8dce0..4209f42 100644
--- a/doc/overview.html
+++ b/doc/overview.html
@@ -116,7 +116,7 @@ the actual state of the machine.
<ul>
<li> Users are expected to write their service definitions - be it
-oneshots, longruns or bundles - in one ore more
+oneshots, longruns or bundles - in one or more
<em>source directories</em>, in the s6-rc
<a href="s6-rc-compile.html#source">source format</a>.
The source format is simple to parse automatically - which is
@@ -163,8 +163,9 @@ for longruns, and a link to the current compiled state database.
<a href="s6-rc-init.html">s6-rc-init</a> initializes the machine state
as "every declared service is down". </li>
<li> <em>stage2</em> should then invoke the
-<a href="s6-rc.html">s6-rc</a> program with the names of the services that
-should be brought up given as arguments. Of course, bundles can be used
+<a href="s6-rc.html">s6-rc</a> program (<tt>s6-rc change</tt>) with, as
+arguments, the names of the services that
+should be brought up. Of course, bundles can be used
for shortcuts. </li>
<li> That's it, the services are up and the initialization should be
over. If the service database has been properly written, a <em>stage2</em>
diff --git a/doc/s6-rc-bundle.html b/doc/s6-rc-bundle.html
index c77f890..7647006 100644
--- a/doc/s6-rc-bundle.html
+++ b/doc/s6-rc-bundle.html
@@ -64,7 +64,7 @@ option to <tt>./configure</tt>. </li>
<li> <tt>-f</tt>&nbsp;: force. s6-rc-bundle will not complain
when given a nonexisting name to delete (it will do nothing), or
when given an existing name to add (it will replace the definition).
-By default, s6-rc-bundle will exit when asked to delete a
+By default, s6-rc-bundle will complain and exit when asked to delete a
nonexistent name or to add an existing name. </li>
</ul>
@@ -124,7 +124,7 @@ deleted from the database. </li>
<li> One argument that is the name of the bundle to add </li>
<li> One block listing the services contained in the
new bundle. The names in the block are resolved before any addition
-is made to the database. </li>
+or deletion is made to the database. </li>
</ul> </li>
</ul>
diff --git a/doc/s6-rc-compile.html b/doc/s6-rc-compile.html
index 8e4b279..51396b3 100644
--- a/doc/s6-rc-compile.html
+++ b/doc/s6-rc-compile.html
@@ -90,8 +90,9 @@ to operate the database. If neither option is used, then root
It is important to <em>only</em> use the <tt>-u</tt> or <tt>-g</tt>
options when the user owning the supervision tree is not root. The
internal s6-rc mechanisms allow uids and gids specified by those
-options to run any program as the user owning the supervision tree;
-if that user is root, this becomes an easy avenue for unwanted
+options to run any oneshot in the compiled service database as the
+user owning the supervision tree;
+if that user is root, this becomes an avenue for unwanted
privilege gain. Only specify users that have the right to operate
the supervision tree!
</p>
@@ -201,7 +202,8 @@ compiled database in an internal form. <tt>up</tt> will be run when
the service is started, and <tt>down</tt> will be executed when the service
is stopped. <tt>up</tt> is mandatory, but <tt>down</tt> is optional;
if no <tt>down</tt> file is provided in the source definition directory,
-then s6-rc will consider that the down transition for this service
+then it is treated as the empty script. If a script is empty,
+then s6-rc will consider that the corresponding transition for this service
does nothing and always succeeds. </li>
</ul>
@@ -302,10 +304,14 @@ use relative paths, not absolute ones.
</p>
<p>
- Note that you cannot create a <tt>down</tt> file in a generated service
+ Note that you cannot create a <tt>./down</tt> file for
+<a href="http://skarnet.org/software/s6/s6-supervise.html">s6-supervise</a>
+in a generated service
directory. Even if such a file exists in the definition directory, it will
-be ignored. This is intentional:
-<a href="s6-rc.html">s6-rc</a> internally uses down files to mark longrun
+be ignored - it will not be replicated in the service directory.
+This is intentional:
+<a href="s6-rc.html">s6-rc</a> internally uses <tt>./down</tt> files in
+the service directories it manages, to mark longrun
services that are down.
</p>
@@ -338,9 +344,7 @@ indefinite number of longrun services this way.
<li> The first producer may declare a name for the whole pipeline, in
its <tt>pipeline-name</tt> file. If it does so, then a bundle is automatically
created with
-the given name, and it contains all the services in the pipeline (plus the
-automatically generated supporting services that open and store the
-pipes). </li>
+the given name, and it contains all the services in the pipeline. </li>
</ul>
<p>
@@ -357,7 +361,8 @@ detect and reject cycles as well as collisions.
</p>
<p>
- The pipe linking a producer and a consumer is created and stored at run-time in a
+ The pipe linking a producer with a consumer is created and stored at
+run-time in a
<a href="http://skarnet.org/software/s6/s6-fdholder-daemon.html">s6-fdholder-daemon</a>
instance managed by an automatically generated longrun service named
<tt>s6rc-fdholder</tt>.
diff --git a/doc/s6-rc-dryrun.html b/doc/s6-rc-dryrun.html
index 0a55fa6..ee23d3b 100644
--- a/doc/s6-rc-dryrun.html
+++ b/doc/s6-rc-dryrun.html
@@ -57,7 +57,8 @@ is 0, s6-rc-dryrun will not print anything to stdout. Default is 1. </li>
milliseconds before exiting. Default is 1000, but when invoked by
<a href="s6-rc.html">s6-rc</a>, it will be the value of the
<em>dryruntimeout</em> argument to the <tt>-n</tt> option. This is
-used to simulate a non-immediate startup or shutdown script. </li>
+used to simulate a start or stop script that does not complete
+immediately. </li>
</ul>
</body>
diff --git a/doc/s6-rc-init.html b/doc/s6-rc-init.html
index 3334525..e5ae884 100644
--- a/doc/s6-rc-init.html
+++ b/doc/s6-rc-init.html
@@ -36,7 +36,7 @@ invocation of the
absolute paths. </li>
<li> s6-rc-init expects to find a <em>compiled service database</em>
in <em>compiled</em>. It expects to be able to create a directory
-at <em>live</em>. It also expects that an instance of
+named <em>live</em>. It also expects that an instance of
<a href="http://skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
is running on <em>scandir</em>. </li>
<li> s6-rc-init initializes the live state in <em>live</em>. It
@@ -44,13 +44,13 @@ declares <em>compiled</em> as the current service database and
sets the state as "all services down". </li>
<li> It then copies verbatim all
the service directories declared by <em>compiled</em> into a
-subdirectory of <em>live</em>, adds down files to the live copies
-and links them into <em>scandir</em>. It then triggers
+subdirectory of <em>live</em>, adds <tt>./down</tt> files to the live copies
+and links those live copies into <em>scandir</em>. It then triggers
<a href="http://skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>,
which will pick up the new service directories and start
<a href="http://skarnet.org/software/s6/s6-supervise.html">s6-supervise</a>
processes on them - but the service themselves will not be started
-right away, because of the down files. </li>
+right away, because of the <tt>./down</tt> files. </li>
<li> s6-rc-init waits for all s6-supervise processes to be
operational, then exits 0. </li>
</ul>
@@ -95,5 +95,21 @@ invocation of the <a href="s6-rc.html">s6-rc change</a> command.)
<em>stage2</em> (by default <tt>/etc/rc.init</tt>) script.
</p>
+<h2> Notes </h2>
+
+<ul>
+ <li> The directory created by s6-rc-init will actually be called
+<em>live</em><tt>:initial</tt>, and <em>live</em> will be a symbolic
+link to that directory. Users should ignore this, and always refer
+to the live directory as <em>live</em> in their future
+<a href="s6-rc.html">s6-rc</a> or <a href="s6-rc-update.html">s6-rc-update</a>
+invocations. The reason for this behaviour is that
+<a href="s6-rc-update.html">s6-rc-update</a> creates another,
+similarly named, directory (<em>live</em><tt>:<em>suffix</em></tt>)
+and updates the live state by atomically changing the target of the
+<em>live</em> symlink - so <em>live</em> will not change names, whereas
+the real directory may.) </li>
+</ul>
+
</body>
</html>
diff --git a/doc/s6-rc-oneshot-run.html b/doc/s6-rc-oneshot-run.html
index c2b422f..351e9e1 100644
--- a/doc/s6-rc-oneshot-run.html
+++ b/doc/s6-rc-oneshot-run.html
@@ -37,8 +37,8 @@ in internal scripts created by
</pre>
<ul>
- <li> s6-rc-oneshot-run executes into the <tt>up</tt> or <tt>down</tt> script,
-depending on its first argument, of the <em>n</em>th oneshot service defined
+ <li> s6-rc-oneshot-run executes into the <tt>up</tt> or <tt>down</tt> script
+of the <em>n</em>th oneshot service defined
in the current compiled service database (i.e. the compiled linked from the
live directory). </li>
</ul>
diff --git a/doc/s6-rc-update.html b/doc/s6-rc-update.html
index 1e56ba2..e9ab43c 100644
--- a/doc/s6-rc-update.html
+++ b/doc/s6-rc-update.html
@@ -43,7 +43,8 @@ situations it cannot solve.
<ul>
<li> s6-rc-update analyzes the current live state, the current compiled service
-database, and the compiled service database contained at <em>newdb</em>. </li>
+database, and the compiled service database contained at <em>newdb</em>
+(which must be an absolute path). </li>
<li> Additionally, it can process an optional <em>conversion file</em> containing
instructions. </li>
<li> It computes the necessary service transitions to safely update the live
@@ -85,7 +86,8 @@ The default is 0, meaning infinite (no timeout). Be aware that timing
out and exiting may leave the live database in an inconsistent state,
so use of this option is not recommended. </li>
<li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: look for the
-live state in <em>live</em>. Default is <tt>/run/s6-rc</tt>.
+live state in <em>live</em>. It must be an absolute path.
+Default is <tt>/run/s6-rc</tt>.
The default can be changed at compile-time by giving the
<tt>--livedir=<em>live</em></tt> option to <tt>./configure</tt>. </li>
<li> <tt>-f&nbsp;<em>convfile</em></tt>&nbsp;: use the conversion
@@ -97,11 +99,11 @@ meaning no special instructions. </li>
<p>
s6-rc-update's job is to ensure consistency of the live state across
-a change of compiled service database. To do so, it must make sure
+a change of compiled service databases. To do so, it must make sure
that the services that are up at the time of its invocation are still
up after its invocation; but service definitions in the new compiled
-may be different from those in the old one; in particular, dependencies
-may change, or a service can change types - a oneshot can become
+may be different from those in the old one - in particular, dependencies
+may change, or a service can change types: a oneshot can become
a longrun and vice-versa, and an atomic service can even become a
bundle.
</p>
@@ -112,7 +114,7 @@ bundle.
s6-rc-update examines atomic services, as defined in the old compiled,
that are up at invocation time, and computes what is necessary for the
"same" service, as defined in the new compiled, to be up. Barring
-conversion file instructions, the service is "the same" if it has the
+instructions from the conversion file, the service is "the same" if it has the
same name in the new compiled, no matter its type.
</p>
@@ -208,11 +210,7 @@ matter whether a service is renamed or not, changing its type will force a
restart.
</p>
-<p>
- Note that renaming a longrun without restarting it will keep the same
-<a href="http://skarnet.org/software/s6/s6-supervise.html">s6-supervise</a>
-process supervising the longrun: this process will appear in a
-<tt>ps</tt> output as supervising the old name. This is only cosmetic and
+<tt>ps</tt> output as supervising the old name. This is purely cosmetic and
will have no impact on the service; nevertheless, if you wish to avoid that,
simply force a restart on every service you rename.
</p>
@@ -258,9 +256,9 @@ real directory. </li>
but not restarted, the
<a href="http://skarnet.org/software/s6/s6-supervise.html">s6-supervise</a>
process in charge of it will still show up in the process list as
-<tt>s6-supervise <em>oldname</em></tt>. This is purely cosmetic. To make
-s6-supervise pick up the new name, make sure to restart the service when
-invoking s6-rc-update. </li>
+<tt>s6-supervise <em>oldname</em></tt>. This is purely cosmetic and
+will have no impact on the service; nevertheless, if you wish to avoid that,
+simply force a restart on every longrun you rename. </li>
<li> After a s6-rc-update invocation, the old compiled service database
is left unchanged where it was, and the new compiled
service database is used in-place. If the machine is rebooted, the
diff --git a/doc/s6-rc.html b/doc/s6-rc.html
index 8eb0753..47afd3f 100644
--- a/doc/s6-rc.html
+++ b/doc/s6-rc.html
@@ -35,8 +35,9 @@ should be achieved by a single <tt>s6-rc change</tt> invocation.
</p>
<p>
- s6-rc should only be run as root, especially when asking for a state
-change.
+ Except in test installations with specifically made compiled
+databases and live directories, s6-rc should only be run as root -
+especially when asking for a state change.
</p>
<h2> Interface </h2>
@@ -50,9 +51,7 @@ change.
<ul>
<li> s6-rc expects to find a functional <em>live state</em> in
-<em>live</em> (by default <tt>/run/s6-rc</tt>, unless changed when the package
-was compiled). The live state is
-normally created at boot time by
+<em>live</em>. The live state is normally created at boot time by
<a href="s6-rc-init.html">s6-rc-init</a>. If the live state is
invalid, s6-rc complains and exits 4. </li>
<li> Depending on the arguments given, it prints the requested
@@ -78,8 +77,9 @@ state change. </li>
The arguments <em>servicenames...</em> may be atomic services or
bundles; they are resolved into a set of atomic services, which is
called the <em>selection</em>. If the <tt>-a</tt> option is present,
-the current set of <em>up</em> services is added to the selection.
-The s6-rc command operates on the selection.
+the current set of active services (i.e. services that are up) is
+added to the selection.
+<strong>The s6-rc command always operates on the selection</strong>.
</p>
<h2> Options </h2>
@@ -95,11 +95,6 @@ giving the <tt>--livedir=<em>live</em></tt> option to <tt>./configure</tt>. </li
the selection. This is useful for instance at
shutdown time: <tt>s6-rc -da change</tt>
will stop all services. </li>
- <li> <tt>-X</tt>&nbsp;: don't lock the live state or the compile
-database. This option should never be used when s6-rc is run
-manually; it's only used by commands such as
-<a href="s6-rc-update.html">s6-rc-update</a> that spawn a s6-rc
-instance while already holding the necessary locks. </li>
</ul>
<h3> Up or down </h3>
@@ -259,7 +254,7 @@ should work with s6-rc with no additional effort.
<h4> Oneshot transitions </h4>
<p>
- Transitions for oneshot services involve running the <em>up</em>
+ Transitions for oneshot services amount to running the <em>up</em>
or <em>down</em> script for the service; those scripts are stored
in the compiled service database that is linked from the live state.
The transition is considered successful if the script exits zero,
diff --git a/doc/why.html b/doc/why.html
index 829b31a..8c4c869 100644
--- a/doc/why.html
+++ b/doc/why.html
@@ -26,14 +26,15 @@
<a href="http://smarden.org/runit/">runit</a>,
<a href="http://b0llix.net/perp/">perp</a> or
<a href="http://cr.yp.to/daemontools.html">daemontools</a>
-define a <em>service</em> as a long-lived process, a.k.a a
+define a <em>service</em> as a long-lived process, a.k.a
daemon. They provide tools to run the daemon in a reproducible
way in a controlled environment and keep it alive if it dies;
they also provide daemon management tools to, among others,
send signals to the daemon without knowing its PID. They can
-control individual long-lived process perfectly well, and
+control individual long-lived processes perfectly well, and
<a href="http://skarnet.org/software/s6/">s6</a> also provides
-tools to manage a whole supervision tree.
+tools to manage a whole supervision tree. To any system administrator
+concerned about reliability, supervision suites are a good thing.
</p>
<p>
@@ -45,22 +46,24 @@ tools to manage a whole supervision tree.
management is doable on simple systems, where there aren't
many dependencies, and where most of the one-time initialization
can take place in stage 1, before any daemons are launched.
-On embedded systems, for instance, this is perfectly reasonable.
+On some embedded systems, for instance, this is perfectly reasonable.
</p>
<p>
- On bigger systems, though, it is more problematic. Here are a few
+ On other systems, though, it is more problematic. Here are a few
issues encountered:
</p>
<ul>
<li> With a pure supervision tree, all daemons are launched in
parallel; if their dependencies are not met, daemons just die, and
-are restarted by the supervisors, and so on; so eventually everything
+are restarted by the supervisors, and so on; so eventually the
+dependency tree is correctly built and everything
is brought up. This is okay with lightweight daemons that do not take
up too many resources when starting; but with heavyweight daemons,
-bringing them up at the wrong time can significantly expend CPU and
-increase the total booting time. </li>
+bringing them up at the wrong time can expend CPU or cause heavy
+disk access, and
+increase the total booting time significantly. </li>
<li> The <a href="http://smarden.org/runit/">runit</a> model of
separating one-time initialization (stage 1) and daemon management
(stage 2) does not always work: some one-time initialization may
@@ -73,7 +76,7 @@ alive and ease their administration; dependency across those
daemons is not their concern, and one-time initialization scripts
are entirely foreign to them. So a situation like <tt>udevd</tt>
where it is necessary to interleave daemons and one-time scripts
-is very badly handled by them. </li>
+is not handled properly by them. </li>
</ul>
<p>
@@ -140,9 +143,10 @@ that it has a significant performance impact.
<p>
(Note that <a href="https://wiki.gentoo.org/wiki/Project:OpenRC">OpenRC</a>
has an option to start services in parallel, but at the time of this
-writing, it has no readiness notification mechanism when this option
-is used, and all the services are started in parallel without regard
-for the dependency graph, so it is not reliable.)
+writing, it uses polling on a lock file to check whether a service
+has completed all its dependencies; this is heavily prone to race
+conditions, and is not the correct mechanism to ensure proper service
+ordering, so this option cannot be considered reliable.)
</p>
<p>
@@ -163,8 +167,8 @@ boilerplate, which adds to the inefficiency problem.
the flaws of traditional service starters, and provide supervision,
dependency management and sometimes readiness notification, while
reducing the amount of scripting needed.
-Unfortunately, the results were tightly integrated, monolithic init
-systems straying very far away from Unix core principles, with
+Unfortunately, the results are tightly integrated, monolithic init
+systems straying far away from Unix core principles, with
design flaws that make the historical inits' design flaws look like
a joke.
</p>
@@ -174,7 +178,10 @@ a joke.
one. On the front page, in the "feature highlights" section:
"Tasks and Services are started and stopped
by events. Events are generated as tasks and services are started
-and stopped." Do you understand what that means? I don't. </li>
+and stopped." Do you understand what that means? I don't. Also,
+Upstart was the first system that used <tt>ptrace</tt> on the
+processes it spawned in order to keep track of their forks. If
+you don't know what that means: it was pure insanity. </li>
<li> <a href="https://en.wikipedia.org/wiki/Launchd">launchd</a>,
Darwin's init and service manager. The wikipedia page (linked here
because Apple doesn't see fit to provide a documentation page for
@@ -216,8 +223,9 @@ such as minimal software dependencies and shortness of code paths. </li>
</ul>
<p>
- Pages and pages could be written about the shortcomings of integrated
-init systems; one fact remains - they are not a satisfying solution
+ Pages and pages could be - and have been - written about the shortcomings
+of integrated
+init systems, but one fact remains: they are not a satisfying solution
to the problem of service management under Unix.
</p>
diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c
index 6704e93..66c956f 100644
--- a/src/s6-rc/s6-rc-update.c
+++ b/src/s6-rc/s6-rc-update.c
@@ -753,7 +753,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
/* Down transition */
{
- char const *newargv[11 + (dryrun * 5) + want_count(oldstate, oldn)] ;
+ char const *newargv[12 + (dryrun * 4) + want_count(oldstate, oldn)] ;
unsigned int m = 0, i = oldn ;
int wstat ;
char vfmt[UINT_FMT] ;
@@ -775,7 +775,8 @@ int main (int argc, char const *const *argv, char const *const *envp)
newargv[m++] = tfmt ;
newargv[m++] = "-l" ;
newargv[m++] = live ;
- newargv[m++] = "-Xd" ;
+ if (!dryrun) newargv[m++] = "-X" ;
+ newargv[m++] = "-d" ;
newargv[m++] = "--" ;
newargv[m++] = "change" ;
while (i--) if (oldstate[i] & 2)
@@ -818,7 +819,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
/* Up transition */
{
- char const *newargv[11 + (dryrun * 5) + want_count(newstate, newn)] ;
+ char const *newargv[12 + (dryrun * 4) + want_count(newstate, newn)] ;
unsigned int m = 0, i = newn ;
char vfmt[UINT_FMT] ;
char tfmt[UINT_FMT] ;
@@ -839,7 +840,8 @@ int main (int argc, char const *const *argv, char const *const *envp)
newargv[m++] = tfmt ;
newargv[m++] = "-l" ;
newargv[m++] = live ;
- newargv[m++] = "-Xua" ;
+ if (!dryrun) newargv[m++] = "-X" ;
+ newargv[m++] = "-u" ;
newargv[m++] = "--" ;
newargv[m++] = "change" ;
while (i--) if (newstate[i] & 2)