RE: thoughts on rudimentary dependency handling

From: Avery Payne <>
Date: Wed, 7 Jan 2015 14:25:28 -0800

On Wed, Jan 7, 2015 at 7:23 AM, Steve Litt <>
> I'm pretty sure this conforms to James' preference (and mine probably)
> that it be done in the config and not in the init program.
> To satisfy Laurent's preference, everything but the exec cron -f could
> be commented out, and if the user wants to use this, he/she can
> uncomment all the rest. Or your run script writing program could have an
> option to write the dependencies, or not.

I've pretty much settled on a system-wide switch in sv/.env (which in the
scripts will show up as ../.env). The switch will, by default, follow
Laruent's behavior of "naive launching", ie. no dependencies are up,
missing dependencies cause failures, and the admin must check logging for
notifications. Enabling the feature would be as simple as

echo "1" > /etc/sv/.env/NEEDS_ENABLED

...and every new service launch would receive it. You could also
force-reload with a restart command. Without the flag, the entire chunk of
dependency code is bypassed and the launch continues "as normal".

The goal is the same but the emphasis has changed. This will be considered
a fall-back feature for those systems that do not have such a tool
available, or have constraints that force the continued use of a shell
launcher. It is the option of last resort, and while I think I can make it
work fairly consistently, it will come with some warnings in the wiki. For
Laurent, he wouldn't even need to lift a finger - it fully complies with
his desires out of the box. ;-)

As new tools emerge in the future, I will be able to write a shunt into the
script that detects the tool and uses it instead of the built-in scripted
support. This will allow Laurent's work to be integrated without messing
anything up, so the behavior will be the same, but implemented differently.

Finally, with regard to the up vs actually running issue, I'm not even
going to try and address it due to the race conditions involved. The best
I will manage is to first issue the up, then do a service check to confirm
that it didn't die upon launch, which for a majority (but not all) cases
should suffice. Yes, there are still race conditions, but that is fine -
I'm falling back to the original model of "service fails continually until
it succeeds", which means a silently-failed "child" dependency that was
missed by the "check" command will still cause the "parent" script to fail,
because the daemon itself will fail. It is a crude form of graceful
failure. So the supervisor starts the parent again...and again...until the
truant dependency is up and running, at which point it will bring the
parent up. Like I said, this will be a fall-back feature, and it will have
minor annoyances or issues.

Right now the biggest problem is handling all of the service tool calls.
They all have the same grammar, (tool) (command) (service name), so I can
script that easily. Getting the tools to show up as the correct command
and command option is something else, and I'm working on a way to wedge it
into the use-* scripts so that the tools are set up out of the box all at
the same time. This will create $SVCTOOL, and a set of $CMDDOWN, $CMDUP,
$CMDCHECK, etc. that will be used in the scripts. **Once that is done I
can fully test the rest of the dependency concept and get it fleshed out.**
 If anyone wants to see it, email me directly and I'll pass it along, but
there's not much to look at.

Unfortunately, the envdir tool, which I use to abstract away the daemons
and settings, only chain-loads; it would be nice if it had a persistence
mechanism, so that I could "load once" for the scope of the shell script.
Because of that, there will be some odd scripting in there that pulls the
values, i.e.

[ -f ../.env/CMDUP ] || echo "$(basename $0): fatal error: unable to load
CMDUP" && exit 99
CMDUP=$(cat ../.env/CMDUP)

with an entry for each command.

> In my 5 minute thought process, the last remaining challenge, and it's
> a big one, is to get the right service names for the dependencies, and
> that requires a standardized list, because, as far as I know, the
> daemontools-inspired inits don't have "provides". Such a list would be
> hard enough to develop and have accepted, but <tinfoil_hat>I expect our
> friends at Red Hat to start changing the names in order to mess us
> up</tinfoil_hat>.

Using a "./provides" as a rendezvous or advertisement mechanism I think is
nice-in-concept but difficult-in-practice. Give it a bit more thought and
you'll see that we're not just talking about the *service* but also any
*protocol* to speak with it and one or more *data transport* needed to talk
to the service. Example: MySQL using a port number bound to, vs
MySQL using a file socket. Both provide a MySQL database and MySQL's
binary client protocol, but the transport is entirely different. Another
example: exim4 vs postfix vs qmail vs (insert favorite SMTP server here).
All speak SMTP - but some do LMTP at the same time (in either sockets or
ports), so there are actually two transports AND two protocols that need to
be expressed. Because the number of possibilities starts to grow it
becomes less and less feasible for me to script it...more likely, this is a
job for a program in C and some data structures, something that Laurent is
already pondering for the future.

With regard to naming (malicious or not), I'm side-stepping the entire
issue. With the new run-envdir script, the old dependency of "the
directory must match the name" is gone. In order for things to break due
to naming conventions, the compiled daemon binaries themselves would need
their names to change, because those names are stored in self-contained
envdir variables. This allows users to change the directory name but still
keep the service name, at the cost of breaking the dependency fall-back
feature (which will complain about the dangling symlink and fail-on-purpose
in the script as a part of dependency startup, so it's "safe" but
"ineffective"). It also allows you, if you are crazy enough, to do the
runit SysV substitution where it will intercept SysV init.d scripts and
call runit instead, although I don't recommend it. When the project
reaches 1.0 in the distant future, it won't matter anyways - there will be
near-complete coverage and the odds of needing init.d scripts hanging
around drops to almost nothing.

> In spite of the challenges, what you're doing here is so valuable that
> it *must* be done. I believe that what you're contemplating busts the
> whole situation wide open, relieves "upstreams" of all init
> responsibility except to declare their dependencies by their official
> names, makes it almost trival for any distro to adopt a
> daemontools-inspired init, and makes it doable for a modestly smart
> user to jumper around their existing init system, if that's what they
> want to do.

Sshh! Don't talk too'll expose my secret plan! :-) But
thanks for saying that, and you are right. The drive of the project is to
increase accessibility of the frameworks, and in doing so, increase
adoption. Adoption will lead to feedback, which leads to improvements,
which drives development forward, increasing accessibility, etc. in a
continuous feedback loop.
Received on Wed Jan 07 2015 - 22:25:28 UTC

This archive was generated by hypermail 2.3.0 : Sun May 09 2021 - 19:44:19 UTC