diff --git a/repos/os/include/init/child.h b/repos/os/include/init/child.h index e3c8c63b9d..8a42415fe8 100644 --- a/repos/os/include/init/child.h +++ b/repos/os/include/init/child.h @@ -28,6 +28,7 @@ namespace Init { + class Buffered_xml; class Routed_service; class Name_registry; class Child_registry; @@ -252,6 +253,42 @@ namespace Init { } +class Init::Buffered_xml +{ + private: + + Allocator &_alloc; + char const * const _ptr; /* pointer to dynamically allocated buffer */ + Xml_node const _xml; /* referring to buffer of '_ptr' */ + + /** + * \throw Allocator::Out_of_memory + */ + static char const *_init_ptr(Allocator &alloc, Xml_node node) + { + char *ptr = (char *)alloc.alloc(node.size()); + Genode::memcpy(ptr, node.addr(), node.size()); + return ptr; + } + + public: + + /** + * Constructor + * + * \throw Allocator::Out_of_memory + */ + Buffered_xml(Allocator &alloc, Xml_node node) + : + _alloc(alloc), _ptr(_init_ptr(alloc, node)), _xml(_ptr, node.size()) + { } + + ~Buffered_xml() { _alloc.free(const_cast(_ptr), _xml.size()); } + + Xml_node xml() const { return _xml; } +}; + + /** * Init-specific representation of a child service */ @@ -333,6 +370,11 @@ class Init::Child : Child_policy, Child_service::Wakeup */ struct Id { unsigned value; }; + struct Default_route_accessor + { + virtual Xml_node default_route() = 0; + }; + private: friend class Child_registry; @@ -349,9 +391,9 @@ class Init::Child : Child_policy, Child_service::Wakeup List_element _list_element; - Xml_node _start_node; + Reconstructible _start_node; - Xml_node _default_route_node; + Default_route_accessor &_default_route_accessor; Name_registry &_name_registry; @@ -522,6 +564,7 @@ class Init::Child : Child_policy, Child_service::Wakeup * \throw Region_map::Attach_failed failed to temporarily attach * config dataspace to local address * space + * \throw Allocator::Out_of_memory could not buffer the XML start node */ Child(Env &env, Allocator &alloc, @@ -529,7 +572,7 @@ class Init::Child : Child_policy, Child_service::Wakeup Id id, Report_update_trigger &report_update_trigger, Xml_node start_node, - Xml_node default_route_node, + Default_route_accessor &default_route_accessor, Name_registry &name_registry, long prio_levels, Affinity::Space const &affinity_space, @@ -539,8 +582,8 @@ class Init::Child : Child_policy, Child_service::Wakeup _env(env), _alloc(alloc), _verbose(verbose), _id(id), _report_update_trigger(report_update_trigger), _list_element(this), - _start_node(start_node), - _default_route_node(default_route_node), + _start_node(_alloc, start_node), + _default_route_accessor(default_route_accessor), _name_registry(name_registry), _unique_name(start_node, name_registry), _binary_name(_binary_name_from_xml(start_node, _unique_name)), @@ -700,9 +743,9 @@ class Init::Child : Child_policy, Child_service::Wakeup return Route { _session_requester.service() }; try { - Xml_node route_node = _default_route_node; + Xml_node route_node = _default_route_accessor.default_route(); try { - route_node = _start_node.sub_node("route"); } + route_node = _start_node->xml().sub_node("route"); } catch (...) { } Xml_node service_node = route_node.sub_node(); @@ -862,7 +905,7 @@ class Init::Child : Child_policy, Child_service::Wakeup void exit(int exit_value) override { try { - if (_start_node.sub_node("exit").attribute_value("propagate", false)) { + if (_start_node->xml().sub_node("exit").attribute_value("propagate", false)) { _env.parent().exit(exit_value); return; } diff --git a/repos/os/src/init/main.cc b/repos/os/src/init/main.cc index 4f24370969..62002f33eb 100644 --- a/repos/os/src/init/main.cc +++ b/repos/os/src/init/main.cc @@ -384,7 +384,7 @@ class Init::State_reporter : public Report_update_trigger }; -struct Init::Main : State_reporter::Producer +struct Init::Main : State_reporter::Producer, Child::Default_route_accessor { Env &_env; @@ -398,6 +398,8 @@ struct Init::Main : State_reporter::Producer Reconstructible _verbose { _config.xml() }; + Constructible _default_route; + unsigned _child_cnt = 0; void _handle_resource_avail() { } @@ -411,6 +413,15 @@ struct Init::Main : State_reporter::Producer _children.report_state(xml, detail); } + /** + * Default_route_accessor interface + */ + Xml_node default_route() override + { + return _default_route.constructed() ? _default_route->xml() + : Xml_node(""); + } + State_reporter _state_reporter { _env, *this }; Signal_handler
_resource_avail_handler { @@ -463,10 +474,8 @@ void Init::Main::_handle_config() catch (...) { } /* determine default route for resolving service requests */ - Xml_node default_route_node(""); try { - default_route_node = - _config.xml().sub_node("default-route"); } + _default_route.construct(_heap, _config.xml().sub_node("default-route")); } catch (...) { } /* create aliases */ @@ -489,7 +498,7 @@ void Init::Main::_handle_config() Init::Child(_env, _heap, *_verbose, Init::Child::Id { ++_child_cnt }, _state_reporter, - start_node, default_route_node, + start_node, *this, _children, read_prio_levels(_config.xml()), read_affinity_space(_config.xml()), _parent_services, _child_services)); @@ -500,6 +509,8 @@ void Init::Main::_handle_config() * by the Rom_connection constructor. */ } + catch (Allocator::Out_of_memory) { + warning("local memory exhausted during child creation"); } catch (Ram_session::Alloc_failed) { warning("failed to allocate memory during child construction"); } catch (Child::Missing_name_attribute) {