From 9b0fbf000eaaa5e03234a2f62ce6ce992798b089 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Tue, 11 Feb 2020 16:42:31 +0100 Subject: [PATCH] sandbox: support for local state-report handling Fixes #3647 --- repos/os/include/os/sandbox.h | 21 +++++++- repos/os/src/init/main.cc | 54 +++++++++++++++++++-- repos/os/src/lib/sandbox/library.cc | 23 +++++++-- repos/os/src/lib/sandbox/state_reporter.h | 58 ++++++++--------------- repos/os/src/test/sandbox/main.cc | 8 +++- 5 files changed, 115 insertions(+), 49 deletions(-) diff --git a/repos/os/include/os/sandbox.h b/repos/os/include/os/sandbox.h index 6e533ffae..c7a64fe8f 100644 --- a/repos/os/include/os/sandbox.h +++ b/repos/os/include/os/sandbox.h @@ -32,6 +32,18 @@ class Genode::Sandbox : Noncopyable template class Local_service; + /** + * Interface invoked each time an interesting state change occurs + * + * The handler is supposed to inspect the state as provided by + * the 'generate_state_report' method and respond by adjusting + * the sandbox configuration via 'apply_config'. + */ + struct State_handler : Interface + { + virtual void handle_sandbox_state() = 0; + }; + private: friend class Local_service_base; @@ -46,9 +58,16 @@ class Genode::Sandbox : Noncopyable public: - Sandbox(Env &env); + Sandbox(Env &, State_handler &); void apply_config(Xml_node const &); + + /** + * Generate state report as configured by the config node + * + * \throw Xml_generator::Buffer_exceeded + */ + void generate_state_report(Xml_generator &) const; }; diff --git a/repos/os/src/init/main.cc b/repos/os/src/init/main.cc index 47f4217b3..7b69c9572 100644 --- a/repos/os/src/init/main.cc +++ b/repos/os/src/init/main.cc @@ -15,6 +15,7 @@ #include #include #include +#include namespace Init { @@ -24,11 +25,11 @@ namespace Init { } -struct Init::Main +struct Init::Main : Sandbox::State_handler { Env &_env; - Sandbox _sandbox { _env }; + Sandbox _sandbox { _env, *this }; Attached_rom_dataspace _config { _env, "config" }; @@ -37,15 +38,62 @@ struct Init::Main Signal_handler
_resource_avail_handler { _env.ep(), *this, &Main::_handle_resource_avail }; + Constructible _reporter { }; + + size_t _report_buffer_size = 0; + void _handle_config() { _config.update(); - _sandbox.apply_config(_config.xml()); + + Xml_node const config = _config.xml(); + + bool reporter_enabled = false; + config.with_sub_node("report", [&] (Xml_node report) { + + reporter_enabled = true; + + /* (re-)construct reporter whenever the buffer size is changed */ + Number_of_bytes const buffer_size = + report.attribute_value("buffer", Number_of_bytes(4096)); + + if (buffer_size != _report_buffer_size || !_reporter.constructed()) { + _report_buffer_size = buffer_size; + _reporter.construct(_env, "state", "state", _report_buffer_size); + } + }); + + if (_reporter.constructed()) + _reporter->enabled(reporter_enabled); + + _sandbox.apply_config(config); } Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; + /** + * Sandbox::State_handler interface + */ + void handle_sandbox_state() override + { + try { + Reporter::Xml_generator xml(*_reporter, [&] () { + _sandbox.generate_state_report(xml); }); + } + catch (Xml_generator::Buffer_exceeded) { + + error("state report exceeds maximum size"); + + /* try to reflect the error condition as state report */ + try { + Reporter::Xml_generator xml(*_reporter, [&] () { + xml.attribute("error", "report buffer exceeded"); }); + } + catch (...) { } + } + } + Main(Env &env) : _env(env) { _config.sigh(_config_handler); diff --git a/repos/os/src/lib/sandbox/library.cc b/repos/os/src/lib/sandbox/library.cc index 39b9867b9..28b60c491 100644 --- a/repos/os/src/lib/sandbox/library.cc +++ b/repos/os/src/lib/sandbox/library.cc @@ -145,7 +145,7 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer, */ Cap_quota default_caps() override { return _default_caps; } - State_reporter _state_reporter { _env, *this }; + State_reporter _state_reporter; Heartbeat _heartbeat { _env, _children, _state_reporter }; @@ -157,12 +157,19 @@ struct Genode::Sandbox::Library : ::Sandbox::State_reporter::Producer, Server _server { _env, _heap, _child_services, _state_reporter }; - Library(Env &env, Heap &heap, Registry &local_services) + Library(Env &env, Heap &heap, Registry &local_services, + State_handler &state_handler) : - _env(env), _heap(heap), _local_services(local_services) + _env(env), _heap(heap), _local_services(local_services), + _state_reporter(_env, *this, state_handler) { } void apply_config(Xml_node const &); + + void generate_state_report(Xml_generator &xml) const + { + _state_reporter.generate(xml); + } }; @@ -612,9 +619,15 @@ void Genode::Sandbox::apply_config(Xml_node const &config) } -Genode::Sandbox::Sandbox(Env &env) +void Genode::Sandbox::generate_state_report(Xml_generator &xml) const +{ + _library.generate_state_report(xml); +} + + +Genode::Sandbox::Sandbox(Env &env, State_handler &state_handler) : _heap(env.ram(), env.rm()), - _library(*new (_heap) Library(env, _heap, _local_services)) + _library(*new (_heap) Library(env, _heap, _local_services, state_handler)) { } diff --git a/repos/os/src/lib/sandbox/state_reporter.h b/repos/os/src/lib/sandbox/state_reporter.h index b354e6e51..52d3c9765 100644 --- a/repos/os/src/lib/sandbox/state_reporter.h +++ b/repos/os/src/lib/sandbox/state_reporter.h @@ -15,14 +15,15 @@ #define _LIB__SANDBOX__STATE_REPORTER_H_ /* Genode includes */ -#include #include +#include /* local includes */ #include "report.h" namespace Sandbox { class State_reporter; } + class Sandbox::State_reporter : public Report_update_trigger { public: @@ -35,14 +36,12 @@ class Sandbox::State_reporter : public Report_update_trigger private: + using State_handler = Genode::Sandbox::State_handler; + Env &_env; Producer &_producer; - Constructible _reporter { }; - - size_t _buffer_size = 0; - Reconstructible _report_detail { }; uint64_t _report_delay_ms = 0; @@ -68,62 +67,43 @@ class Sandbox::State_reporter : public Report_update_trigger bool _scheduled = false; + State_handler &_state_handler; + void _handle_timer() { _scheduled = false; - try { - Reporter::Xml_generator xml(*_reporter, [&] () { - - if (_version.valid()) - xml.attribute("version", _version); - - _producer.produce_state_report(xml, *_report_detail); - }); - } - catch(Xml_generator::Buffer_exceeded) { - - error("state report exceeds maximum size"); - - /* try to reflect the error condition as state report */ - try { - Reporter::Xml_generator xml(*_reporter, [&] () { - xml.attribute("error", "report buffer exceeded"); }); - } - catch (...) { } - } + _state_handler.handle_sandbox_state(); } public: - State_reporter(Env &env, Producer &producer) + State_reporter(Env &env, Producer &producer, State_handler &state_handler) : - _env(env), _producer(producer) + _env(env), _producer(producer), + _state_handler(state_handler) { } + void generate(Xml_generator &xml) const + { + if (_version.valid()) + xml.attribute("version", _version); + + if (_report_detail.constructed()) + _producer.produce_state_report(xml, *_report_detail); + } + void apply_config(Xml_node config) { try { Xml_node report = config.sub_node("report"); - /* (re-)construct reporter whenever the buffer size is changed */ - Number_of_bytes const buffer_size = - report.attribute_value("buffer", Number_of_bytes(4096)); - - if (buffer_size != _buffer_size || !_reporter.constructed()) { - _buffer_size = buffer_size; - _reporter.construct(_env, "state", "state", _buffer_size); - } - _report_detail.construct(report); _report_delay_ms = report.attribute_value("delay_ms", 100UL); - _reporter->enabled(true); } catch (Xml_node::Nonexistent_sub_node) { _report_detail.construct(); _report_delay_ms = 0; - if (_reporter.constructed()) - _reporter->enabled(false); } bool trigger_update = false; diff --git a/repos/os/src/test/sandbox/main.cc b/repos/os/src/test/sandbox/main.cc index e597df2f8..122f330ce 100644 --- a/repos/os/src/test/sandbox/main.cc +++ b/repos/os/src/test/sandbox/main.cc @@ -48,7 +48,13 @@ struct Test::Main : Sandbox::Local_service_base::Wakeup Heap _heap { _env.ram(), _env.rm() }; - Sandbox _sandbox { _env }; + struct State_handler : Sandbox::State_handler + { + void handle_sandbox_state() override { } + + } _state_handler { }; + + Sandbox _sandbox { _env, _state_handler }; typedef Sandbox::Local_service Log_service;