Just a small hint-file for me to see how cinit works: - cinit starts * cinit executes either init or a profile - the dependency-tree begins - now cinit begins to try to execute the dependencies * first the needs (if those fail, wants are never called) - fork() for every dependency? -------------------------------------------------------------------------------- another idea: - cinit starts - cinit reads the full depedency tree * it builds n-depth trees * it begins at the set init service (profile or init!) * init is the first entry. always. * read full service information (like on/off/params/respawn) * design of each tree element: see below - add a tree for the needs - add a tree for the wants - the elements have links, one service is created only once - after the tree is created, execution begins * begin from the bottom * save a pointer to the last level somehow before? Pre calculation: - need to act on changes (some kind of file watcher) * need to keep status (?) * what with now missing needs / wants? - missing needs: shutdown now missing needs? - simply ignore them? - shut them down if not needed (no one has a link in needs?) * -------------------------------------------------------------------------------- Sample dependency tree: init / \ needs wants / | \ / | \ a b c d e f / | \ / | \ needs needs needs END needs END / | \ \ | | | | b c d c f a e a -------------------------------------------------------------------------------- How this would be sorted:: init: needs: a b c wants: d e f a: needs: b c d b: needs: c f c: needs: a e d: - e: needs: a f: - -------------------------------------------------------------------------------- So in this case, cinit may start services the following way: d f -> Wouldn't be possible in pre-calculation, because of circular dependencies. -------------------------------------------------------------------------------- Try a 'real' dependency tree: a needs b c d b needs c d c and d do not need other stuff -------------------------------------------------------------------------------- Now cinit would it do the following way: start c, start d b will be started, as soon as c and d successfully finish as soon as b is finished, a will be started -------------------------------------------------------------------------------- Now let's think about how this could look like in code... - when we built up the tree, we have some ends (n to say) - we can / must start starting (;-) at the end - we would have more than one line back (z may be needed by c, i, and a) * like in "c is needed by s, c, o" * maxdepth counter? * asynchronous rollback? --> to think more about it! -------------------------------------------------------------------------------- tree elements: * name (= path) * on, off, +params * respawn_delay - -1 if not respawning - >= 0 time to wait between restart * status - NOT STARTED (status on initialisation) - RESPAWNING (running, respawning) - RESPAWN_DELAY (waiting to respawn it) - ONCE (started once) * errormsg - pointer to an error message in case of failure * needs - List of services we need * wants - List of services we want * used_by - List of services which use this service -------------------------------------------------------------------------------- Conclusions ------------ cinit as the main executor ~~~~~~~~~~~~~~~~~~~~~~~~~~ If cinit should start all services directly and manage dependencies only internally, it will need to have build a reverse dependency tree, so it begins starting at the end. cinit could execute all possible parallel running services in parallel and open pipes to the (dumb) service executors.