From fcca4f3466fcacc07928fec84062ce111e76611b Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Mon, 14 Jan 2013 12:13:05 +0100 Subject: [PATCH] Init: handle reconfiguration With this change, init becomes able to respond to config changes by restarting the scenario with the new config. To make this feature useful in practice, init must not fail under any circumstances. Even on conditions that were considered as fatal previously and led to the abort of init (such as ambiguous names of the children or misconfiguration in general), init must stay alive and responsive to config changes. --- os/include/init/child.h | 8 ++- os/run/ldso.run | 3 +- os/run/tar_rom.run | 1 + os/src/init/main.cc | 132 +++++++++++++++++++++++++++++----------- os/src/init/target.mk | 2 +- 5 files changed, 106 insertions(+), 40 deletions(-) diff --git a/os/include/init/child.h b/os/include/init/child.h index 36e6c9929..05321e25a 100644 --- a/os/include/init/child.h +++ b/os/include/init/child.h @@ -295,6 +295,13 @@ namespace Init { class Child : Genode::Child_policy { + public: + + /** + * Exception type + */ + class Child_name_is_not_unique { }; + private: friend class Child_registry; @@ -334,7 +341,6 @@ namespace Init { /* check for a name confict with the other children */ if (!registry->is_unique(unique)) { PERR("Child name \"%s\" is not unique", unique); - class Child_name_is_not_unique { }; throw Child_name_is_not_unique(); } diff --git a/os/run/ldso.run b/os/run/ldso.run index 472137ea9..6dbf4b38f 100644 --- a/os/run/ldso.run +++ b/os/run/ldso.run @@ -29,7 +29,7 @@ append qemu_args "-nographic -m 64" run_genode_until "child exited with exit value 0.*\n" 10 # pay only attention to the output of init and its children -grep_output {^\[init} +grep_output {^\[init } unify_output {environ: [a-f0-9]+} "environ: " @@ -54,6 +54,5 @@ compare_output_to { [init -> test-ldso] Libc test: abs(-10): 10 [init -> test-ldso] ================ [init -> test-ldso] - [init] virtual void Genode::Child_policy::exit(int): child exited with exit value 0 } diff --git a/os/run/tar_rom.run b/os/run/tar_rom.run index 795ad87b9..c2543f707 100644 --- a/os/run/tar_rom.run +++ b/os/run/tar_rom.run @@ -35,6 +35,7 @@ install_config { + diff --git a/os/src/init/main.cc b/os/src/init/main.cc index 80686039d..d780379c6 100644 --- a/os/src/init/main.cc +++ b/os/src/init/main.cc @@ -89,15 +89,32 @@ namespace Init { Child_list::insert(&child->_list_element); } + /** + * Unregister child + */ + void remove(Child *child) + { + Child_list::remove(&child->_list_element); + } + /** * Start execution of all children */ - void start() { + void start() + { Genode::List_element *curr = first(); for (; curr; curr = curr->next()) curr->object()->start(); } + /** + * Return any of the registered children, or 0 if no child exists + */ + Child *any() + { + return first() ? first()->object() : 0; + } + /***************************** ** Name-registry interface ** @@ -129,54 +146,97 @@ namespace Init { int main(int, char **) { using namespace Init; - - try { - config_verbose = - Genode::config()->xml_node().attribute("verbose").has_value("yes"); } - catch (...) { } + using namespace Genode; /* look for dynamic linker */ try { - static Genode::Rom_connection rom("ld.lib.so"); - Genode::Process::dynamic_linker(rom.dataspace()); + static Rom_connection rom("ld.lib.so"); + Process::dynamic_linker(rom.dataspace()); } catch (...) { } - static Genode::Service_registry parent_services; - static Genode::Service_registry child_services; - static Child_registry children; - static Genode::Cap_connection cap; + static Service_registry parent_services; + static Service_registry child_services; + static Child_registry children; + static Cap_connection cap; - try { determine_parent_services(&parent_services); } - catch (...) { } + /* + * Signal receiver for config changes + */ + Signal_receiver sig_rec; + Signal_context sig_ctx; + config()->sigh(sig_rec.manage(&sig_ctx)); - /* determine default route for resolving service requests */ - Genode::Xml_node default_route_node(""); - try { - default_route_node = - Genode::config()->xml_node().sub_node("default-route"); } - catch (...) { } + for (;;) { - /* create children */ - try { - Genode::Xml_node start_node = Genode::config()->xml_node().sub_node("start"); - for (;; start_node = start_node.next("start")) { + try { + config_verbose = + config()->xml_node().attribute("verbose").has_value("yes"); } + catch (...) { } - children.insert(new (Genode::env()->heap()) - Child(start_node, default_route_node, &children, - read_prio_levels_log2(), - &parent_services, &child_services, &cap)); + try { determine_parent_services(&parent_services); } + catch (...) { } - if (start_node.is_last("start")) break; + /* determine default route for resolving service requests */ + Xml_node default_route_node(""); + try { + default_route_node = + config()->xml_node().sub_node("default-route"); } + catch (...) { } + + /* create children */ + try { + Xml_node start_node = config()->xml_node().sub_node("start"); + for (;; start_node = start_node.next("start")) { + + try { + children.insert(new (env()->heap()) + Init::Child(start_node, default_route_node, + &children, read_prio_levels_log2(), + &parent_services, &child_services, &cap)); + } + catch (Rom_connection::Rom_connection_failed) { + /* + * The binary does not exist. An error message is printed + * by the Rom_connection constructor. + */ + } + + if (start_node.is_last("start")) break; + } + + /* start children */ + children.start(); } - } - catch (Genode::Xml_node::Nonexistent_sub_node) { - PERR("No children to start"); + catch (Xml_node::Nonexistent_sub_node) { + PERR("No children to start"); } + catch (Config::Invalid) { + PERR("No valid config found"); } + catch (Init::Child::Child_name_is_not_unique) { } + + /* + * Respond to config changes at runtime + * + * If the config gets updated to a new version, we kill the current + * scenario and start again with the new config. + */ + + /* wait for config change */ + sig_rec.wait_for_signal(); + + /* kill all currently running children */ + while (children.any()) { + Init::Child *child = children.any(); + children.remove(child); + destroy(env()->heap(), child); + } + + /* reset knowledge about parent services */ + parent_services.remove_all(); + + /* reload config */ + config()->reload(); } - /* start children */ - children.start(); - - Genode::sleep_forever(); return 0; } diff --git a/os/src/init/target.mk b/os/src/init/target.mk index aabae562c..5c92ec349 100644 --- a/os/src/init/target.mk +++ b/os/src/init/target.mk @@ -1,3 +1,3 @@ TARGET = init SRC_CC = main.cc -LIBS = env cxx server child init_pd_args +LIBS = env cxx server child init_pd_args signal