:: [DNG] ideas for system startup (was…
Top Page
Delete this message
Reply to this message
Author: Rainer Weikusat
Date:  
To: dng
Old-Topics: Re: [DNG] Init scripts in packages
Subject: [DNG] ideas for system startup (was: Init scripts in packages)
Laurent Bercot <ska-devel@???> writes:
> On 07/08/2015 00:09, Rainer Weikusat wrote:


[...]

>> If you're convinced that "rip and replace" is the only
>> viable option then I won't claim that you're wrong because I really
>> don't know. However, until I hit a technical obstacle, I won't be
>> convinced that the existing system can't be fixed (I acknowledge almost
>> all defects you mentioned) and this is based on being familiar (as in 'I
>> wrote the code') with both approaches.
>
> Fine. I'm okay with the burden of proof. Let's take a simple example and
> see how deep we have to dig to make it work.
>
> You have 3 longrun services, A, B and C.
> A and C can take a long time to start and be ready, because they access
> some network server that can be slow, or even fail. But they don't depend
> on anything else than this network server.
> B depends on A. It does not contact the network server, but it consumes
> non-negligible resources on the local machine at startup time.
>
> Your objective is to reach the state where A, B and C are all up and
> ready as quickly and reliably as possible. How do you proceed ?
>
> Serially ? "A start && B start ; C start"
> Not good: you add A's and C's latencies.
>
> Parallely ? "A start & B start & C start"
> Not good: B can be scheduled to start before A, and will crash.


I'm presently not required to handle any services named 'A', 'B' and
'C'. Further, because of a bug/ 'historical feature' in the update-rc.d
script, Debian has been starting almost all services at a uniform
priority of 20 since at least 1998 => 'hard' service interdependencies are
mostly bullshit. Some people like implementing topological sorts and
don't like make despite they consider the concept much more universally
applicable, hence, there's no end of 'dependency-based service
sorters' (could be regarded as some kind of deformation professionelle
because developers usually deal with dependency-based build systems so
"everything must be dependency based").

[...]

> OK, now, how do you detect that A is ready and that you can start B ?
> Well, you need readiness notification, assuming A supports it. You need
> it because you don't want B to crash and restart. And now your rc system
> must implement some support for it.


There's obviously a TOCTOU race here because "A is ready now" doesn't
mean "A is still ready" at any later time. I'm not aware of any actual
system matching the described behaviour but I consider it buggy: If
there's something B can't do without A, it can't do that but it should
try to cope as good as possible, be it only by retrying until A becomes
available or delaying any 'expensive steps' until A became availabe. In
any case, B would need to be able to deal with 'A suddenly goes away'
instead of a series of cascaded crashes ultimatively terminated by
"kernel panic, attempting to kill init".

But since the whole situation is hypothetical, this is nothing but a
speculation.

[...]

> Now, if you try to implement process supervision, dependency management,
> readiness notification and state tracking in pure init scripts, well,
> gl&hf. That's what sysvrc, with tools like start-stop-daemon or other
> horrors, has been trying to do for 10 years, without knowing exactly what
> it was that it was trying to do. The result isn't pretty.


start-stop-daemon is a less ambitious "solve everything somehow related
to process startup in one program" (or a set of tightly coupled
programs) and that's something I consider to be the wrong approach.

> Then systemd came and said "hey look! I can do just that, and more, and
> you don't have to bother anymore with those horrible sysvrc scripts!"
> And what did admins say? YES, PLEASE. And they gobbled up the crap because
> it was coated with the sweet, sweet features. (And, yes, with an unhealthy
> dose of propaganda and bullshit, but if you dig through the bullshit, you
> can find a few things of value.)
>
> I'm saying the same causes will have the same results, and more tweaking
> of the init scripts isn't going to accomplish anything without some serious
> redesign.


Ignoring the code for acquiring configuration information (something the
shell makes very easy), I think an init script should look roughly like
this:

,----
| case "$1" in
|     start)
|         printf 'Starting CA server: ' >&2
| 
|         daemon chdir / monitor -n ca-server u-listen -g $GROUP -m g -l "$SOCKET" ca-server
| 
|         printf 'ca-server\n' >&2
|         ;;
| 
|     stop)
|         printf 'Stopping CA server: ' >&2
| 
|         monitor-ctrl ca-server stop
| 
|         printf 'ca-server\n' >&2
|         ;;
| 
|     restart)
|         printf 'Restarting CA server: ' >&2
| 
|         monitor-ctrl ca-server restart
| 
|         printf 'ca-server\n' >&2
|         ;;
| 
|     *)
|         printf 'Usage: ca-server start|stop|restart\n' >&2
|         exit 1
|         ;;
| esac

`----

As someone else pointed out, the control flow code could be abstracted
away into some kind of 'universal init script' and individual ones would
just need to define the start and stop commands. And there's nothing
horrible about that because anything which can't easily be done with the
Bourne shell language is supposed to provided in from of a 'process/
service management command' written in C which can be used as part of a
complex service invocation command (the one not mentioned so far creates
a listening AF_UNIX stream socket and executes a program for each
connection --- much like inetd but with the 4.2BSD "have to get the
number of processes down, the kernel can't handle that many"
optimizations).

The general idea would be

1) Keep a relatively simple init which kicks off execution of commands in
response to 'change the system state' request and nothing else (get
rid of as much of /etc/inittab as possible at some point in time)

2) Generally, keep the run-level directories, but with better management
tools.

3) Keep using the shell for everything it can easily handle. It's a
highly-level programming language capable enough of handling the
job. "But I don't want to learn an additional programming language,
especially not one which looks like THIS and was designed in the
1970s!" is not a sensible reason for discarding it. Programming has
its fashions and fads, just like everything else, but since "90% of
everything is crap" 'new stuff' is mainly going to be just as bad as
'old stuff', only in a yet unknown way.

4) Provide the acutally missing features, ie "demonstrably required
ones" in form of additional tools which integrate with the existing
system.

In case this demonstrably can't be made to work (and so far, I have no
reason to believe this), 'rewrite the world' is always an option. But
own goals like (this is based on actual experiments someone conducted
some years ago): Rewrote the world, much faster now! [but systemd
actually takes longer to start sendmail than the existing Debian script
for that after replacing a sleep with an inotifywait] shouldn't be
plastered over with more heated rethoric.

NB: That's something I'm incrementally moving towards as part of my
present job but it's decidedly not a high priority task. Should I ever
achieve the blessed status of someone who can do development 'in his
spare time' (instead of, say, mopping the floor or dishwashing) I might
even start to implement (or re-implement) this as free software but
right now, this is just a "food for thought" pipe dream.