From owner-freebsd-current@FreeBSD.ORG Sun Feb 23 09:13:15 2014 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id F370518D for ; Sun, 23 Feb 2014 09:13:14 +0000 (UTC) Received: from theravensnest.org (theraven.freebsd.your.org [216.14.102.27]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id B21B718DF for ; Sun, 23 Feb 2014 09:13:14 +0000 (UTC) Received: from [192.168.0.7] (cpc28-cmbg15-2-0-cust64.5-4.cable.virginm.net [86.27.189.65]) (authenticated bits=0) by theravensnest.org (8.14.7/8.14.5) with ESMTP id s1N9CvGL047899 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Sun, 23 Feb 2014 09:13:00 GMT (envelope-from theraven@FreeBSD.org) Content-Type: text/plain; charset=iso-8859-1 Mime-Version: 1.0 (Mac OS X Mail 7.1 \(1827\)) Subject: Re: libinit idea From: David Chisnall In-Reply-To: Date: Sun, 23 Feb 2014 09:12:52 +0000 Content-Transfer-Encoding: quoted-printable Message-Id: <62A9DF47-C938-464B-92B6-9A2A96B5A9C9@FreeBSD.org> References: To: =?iso-8859-1?Q?Bruno_Lauz=E9?= X-Mailer: Apple Mail (2.1827) Cc: "freebsd-current@freebsd.org" X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Feb 2014 09:13:15 -0000 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 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