Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Feb 2014 09:12:52 +0000
From:      David Chisnall <theraven@FreeBSD.org>
To:        =?iso-8859-1?Q?Bruno_Lauz=E9?= <brunolauze@msn.com>
Cc:        "freebsd-current@freebsd.org" <freebsd-current@freebsd.org>
Subject:   Re: libinit idea
Message-ID:  <62A9DF47-C938-464B-92B6-9A2A96B5A9C9@FreeBSD.org>
In-Reply-To: <BLU179-W28221A0539478FDDF45ADDC6840@phx.gbl>
References:  <BLU179-W28221A0539478FDDF45ADDC6840@phx.gbl>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi Bruno,

To preface this, I'd like to say that I do believe that FreeBSD does =
need a more modern init system.  SMF on Solaris and Launchd on Darwin =
both have some advantages.  These are what I see as the limitations in =
our current design (not in priority order):

1) Options are implicit.  Because init scripts are written in a =
Turing-complete language, including routines scattered across a large =
number of files, it's very difficult for a tool (e.g. a GUI system =
administration tool like the SMF GUI on Solaris) to enumerate all of the =
options.  Additionally, these options are untyped so a GUI that does =
manage to find them can't tell whether it should be displaying a =
checkbox (for a boolean value) or a text field.  Additionally, it can't =
tell what the dependencies are between them.

2) Dependency information between services is poor.  If service A =
depends on B, and B is not running, then starting A should start B.  If =
nothing else depends on B and B was not explicitly started, then B =
should stop.  The last part is the hard one with shell scripts, because =
it requires maintaining the dependency graph and effectively garbage =
collecting it (explicitly started services are roots, dependencies are =
references).

3) It's easy for tools to add lines to rc.conf, it's hard to remove =
them.  If you're administering a large number of nodes, you want to be =
able to push out updates to all, in a way that doesn't clobber local =
changes.  Text file processing here is always going to be a fragile =
hack.

4) Shell scripts are a good tool for invoking complex sequences of =
command-line programs, but have a measurable overhead relative to fork() =
/ exec() for running a single command.  Most rc actions just run a =
single program, we should only be doing a shell invocation for ones that =
are more complex.

5) In a world where we're moving towards sandboxing services via =
Capsicum, the service launcher needs to be able to create services with =
a potentially large set of initial file descriptors (including a socket =
to Casper), based on the configuration policy.

6) As with launchd, it would make sense for a service management =
framework to subsume inetd and cron (and devd!) functionality, because =
timer events, network events, system startup, system shutdown, device =
attachment, and explicit service starting from the command line are even =
sources that trigger changes to the service dependency graph.

7) Inspecting the system status is very hard with the current system.  I =
want to be able to see a list of all running services, along with the =
reason why they were started.

8) Again, in capsicum world we'd like inetd-like functionality for UNIX =
domain sockets, so that it's possible to lazily start things like =
powerboxes.

In terms of design, I don't think that turning rc scripts into libraries =
is a win.  I would like to see them replaced by a declarative config =
file in a structured format that provides dependency information, =
configuration options, and the commands required to start / stop the =
service (which can be shell scripts, but don't have to invoke a shell).  =
The configuration options should be separate from the configuration =
variables, with the former provided by the package and the latter by the =
system administrator.

We already have, in the base system, a library for parsing a structured =
configuration file format that is used for the pkg tools and a library =
with an efficient binary serialisation (libnv) that is used for various =
Capsicum-related functions.  I'd like to see these combined so that in =
embedded devices all of the configuration files could be stored in the =
binary serialisation (which is denser and faster to parse) and turned =
back into the human-readable one only for editing. =20

I do like the idea of an init library, so that the functionality is =
easily reusable and can be run in nested scopes.  I don't think we gain =
anything by rewriting shell scripts in C, other than a maintenance =
headache and a requirement that all port maintainers be fluent C =
programmers...

David


On 22 Feb 2014, at 23:54, Bruno Lauz=E9 <brunolauze@msn.com> wrote:

> https://github.com/brunolauze/libnit
>=20
> I know there's really big debate about init system but here's my =
tentative to propose a new model to replace rc.
>=20
> Let's call it libinit but the name as no significance for now.
>=20
> I started coding a library with the following architecture.
>=20
> the main idea is to rewrite rc in C language.
>=20
> a utility called system would act a little bit like service command =
does.
>=20
> a folder would contains libraries instead of scripts inside =
[target]/etc/rc.d
> so we can add as many librairies a user desire and interlink the order =
of each piece among all like in rc.
>=20
> each library would follow and expose the following pattern:
>=20
> char **provide(); /* returns all the PROVIDE a library contains */
>=20
> then for each provide() value the library would expose :
>=20
> XXX_provide()
> XXX_require()
> XXX_before()
> XXX_keywords()
>=20
> and optionally:
> XXX_canstart();
> XXX_prestart();
> XXX_start();
> XXX_status();
> XXX_stop();
>=20
> and also:
>=20
> XXX_mycommand(int argc, char **argv);
>=20
> essentially repeating the rc.subr  model
>=20
> system utilty would source /etc/defaults/rc.conf, then source result =
of rc_conf_files loaded
>=20
> On init, /sbin/init would call /sbin/system init instead of running =
script /etc/rc
>=20
> on init, system would scan folder (let's suppose /lib/init.d and =
/usr/local/init.d for now)
> try dlopen() each *.so* files
> and grab provide(); xxx_provide(), xxx_require(), xxx_before() and =
xxx_keyword() for each one.
> compile a list of "service" discovered and do an "rcorder".
>=20
> The benefits is to avoid firing so many utility to manage to init the =
system.
>=20
> Replicating all small helper function from rc to C language like =
load_kld would avoid opening a process and do real syscall at moment.
> Heavily use pthread, waitpid, etc...
>=20
> So instead of firing /sbin/devfs /dev rule -s 1 applyset=20
> call direcly what's would run inside devfs -> rule_main in =
src/sbin/devfs/rule.c ...
> cut the fat
>=20
> here's an example to show /etc/rc.d/abi conversion to abi.c
>=20
> abi.h:
> #ifndef __ABI_H__
> #define __ABI_H__
> #include "../default.h"
>=20
> #define PROVIDE         abi
> #define REQUIRE         { "archdep" }
> #define KEYWORD         { NOJAIL }
>=20
> #include "../common.h"
>=20
> #endif
>=20
>=20
> abi.c:
> #include "abi.h"
>=20
> int sysvipc_start()
> {
>         if (load_kld("sysvmsg"))
>                 if (load_kld("sysvsem"))
>                         return load_kld("sysvshm");
>         return -1;
> }
>=20
> int linux_start()
> {
>         return load_kld("linux");
> }
>=20
> int srv4_start()
> {
>         if (load_kld("svr4elf") =3D=3D 0)
>                 return load_kld("svr4");
>         return (-1);
> }
>=20
> #define __canstart
> int abi_canstart()
> {
>         return is_enabled("sysvipc") || is_enabled("linux") || =
is_enabled("srv4");
> }
>=20
> int abi_start()
> {
>         int err1 =3D 0, err2 =3D 0, err3 =3D 0;
>         if (is_enabled("sysvipc")) err1 =3D sysvipc_start();
>         if (is_enabled("linux")) err2 =3D linux_start();
>         if (is_enabled("srv4")) err3 =3D srv4_start();
>         return err1 && err2 && err3;
> }
>=20
> #include "../common.c"
>=20
>=20
> where common.h and common.c implement everything by default a little =
bit like rc.subr does.
> e.g: PID_FILE and COMMAND macros implement the start by itself, etc...
>=20
>=20
> as you can see really similar to what we have in the script file...
>=20
> Then the system utility would also allow digging into the libraries =
with command like:
> system accounting rotatelog
> etc..
>=20
> I uploaded a quick start to show some code and expose more the idea.
>=20
> https://github.com/brunolauze/libinit
>=20
>=20
>=20
> Thanks in advance for your comments. 		 	   		 =
=20
> _______________________________________________
> freebsd-current@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-current
> To unsubscribe, send any mail to =
"freebsd-current-unsubscribe@freebsd.org"
>=20




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?62A9DF47-C938-464B-92B6-9A2A96B5A9C9>