cli_monitor, launcher: handle exiting subsystems

Until now, the CLI monitor and the laucher allowed the user to explitly
kill subsystems but both used to ignore gracefully exiting subsystems.
It was the user's job to remove the remains of those subsystems. The
patch takes the burden of manually killing exited subsystems from the
user.

Fixes #1685
This commit is contained in:
Norman Feske 2015-09-15 15:37:42 +02:00 committed by Christian Helmuth
parent dd13bbb1e2
commit 20f961cbd8
8 changed files with 105 additions and 21 deletions

View File

@ -49,7 +49,10 @@ struct Launcher::Main
*/
Nitpicker::Connection nitpicker;
Subsystem_manager subsystem_manager { ep, cap };
Genode::Signal_rpc_member<Main> _exited_child_dispatcher =
{ ep, *this, &Main::_handle_exited_child };
Subsystem_manager subsystem_manager { ep, cap, _exited_child_dispatcher };
Menu_dialog menu_dialog { ep, cap, *env()->ram_session(), report_rom_slave,
subsystem_manager, nitpicker };
@ -68,6 +71,12 @@ struct Launcher::Main
void handle_xray_update(unsigned);
void _handle_exited_child(unsigned)
{
auto kill_child_fn = [&] (Child_base::Label label) { menu_dialog.kill(label); };
subsystem_manager.for_each_exited_child(kill_child_fn);
}
/**
* Constructor

View File

@ -325,10 +325,9 @@ class Launcher::Menu_dialog : Input_event_handler, Dialog_generator,
if (!_running(hovered))
_start(hovered);
} else {
_touch("");
}
_touch("");
_clicked = Label("");
_click_in_progress = false;
}
@ -360,6 +359,8 @@ class Launcher::Menu_dialog : Input_event_handler, Dialog_generator,
_context_dialog.visible(false);
}
void kill(Child_base::Label const &label) { _kill(label); }
void update()
{
if (_elements.first()) {

View File

@ -73,7 +73,8 @@ class Launcher::Subsystem_manager
Cap_session &cap_session,
size_t ram_quota,
size_t ram_limit,
Signal_context_capability yield_response_sig_cap)
Signal_context_capability yield_response_sig_cap,
Signal_context_capability exit_sig_cap)
:
Child_base(ram,
label.string(),
@ -81,7 +82,8 @@ class Launcher::Subsystem_manager
cap_session,
ram_quota,
ram_limit,
yield_response_sig_cap)
yield_response_sig_cap,
exit_sig_cap)
{ }
};
@ -139,6 +141,8 @@ class Launcher::Subsystem_manager
_try_response_to_resource_request();
}
Genode::Signal_context_capability _exited_child_sig_cap;
Ram _ram { ram_preservation_from_config(),
_yield_broadcast_dispatcher,
_resource_avail_dispatcher };
@ -179,9 +183,10 @@ class Launcher::Subsystem_manager
public:
Subsystem_manager(Server::Entrypoint &ep, Cap_session &cap)
Subsystem_manager(Server::Entrypoint &ep, Cap_session &cap,
Genode::Signal_context_capability exited_child_sig_cap)
:
_ep(ep), _cap(cap)
_ep(ep), _cap(cap), _exited_child_sig_cap(exited_child_sig_cap)
{ }
/**
@ -204,7 +209,8 @@ class Launcher::Subsystem_manager
Child *child = new (env()->heap())
Child(_ram, label, binary_name.string(), _cap,
ram_config.quantum, ram_config.limit,
_yield_broadcast_dispatcher);
_yield_broadcast_dispatcher,
_exited_child_sig_cap);
/* configure child */
try {
@ -232,6 +238,22 @@ class Launcher::Subsystem_manager
}
}
}
/**
* Call functor for each exited child
*
* The functor takes a 'Child_base::Label' as argument.
*/
template <typename FUNC>
void for_each_exited_child(FUNC const &func)
{
Child *next = nullptr;
for (Child *child = _children.first(); child; child = next) {
next = child->next();
if (child->exited())
func(child->label());
}
}
};
#endif /* _SUBSYSTEM_MANAGER_H_ */

View File

@ -26,6 +26,7 @@
/* CLI-monitor includes */
#include <cli_monitor/ram.h>
class Child_base : public Genode::Child_policy
{
public:
@ -94,6 +95,11 @@ class Child_base : public Genode::Child_policy
Genode::Signal_context_capability _yield_response_sigh_cap;
Genode::Signal_context_capability _exit_sig_cap;
/* true if child is scheduled for destruction */
bool _exited = false;
public:
Child_base(Ram &ram,
@ -102,7 +108,8 @@ class Child_base : public Genode::Child_policy
Genode::Cap_session &cap_session,
Genode::size_t ram_quota,
Genode::size_t ram_limit,
Genode::Signal_context_capability yield_response_sig_cap)
Genode::Signal_context_capability yield_response_sig_cap,
Genode::Signal_context_capability exit_sig_cap)
:
_ram(ram),
_label(label),
@ -117,7 +124,8 @@ class Child_base : public Genode::Child_policy
_child(_binary_rom.dataspace(), _resources.pd.cap(),
_resources.ram.cap(), _resources.cpu.cap(),
_resources.rm.cap(), &_entrypoint, this),
_yield_response_sigh_cap(yield_response_sig_cap)
_yield_response_sigh_cap(yield_response_sig_cap),
_exit_sig_cap(exit_sig_cap)
{ }
Label label() const { return _label; }
@ -252,6 +260,11 @@ class Child_base : public Genode::Child_policy
requested_ram_quota());
}
/**
* Return true if child exited and should be destructed
*/
bool exited() const { return _exited; }
/****************************
** Child_policy interface **
@ -311,6 +324,15 @@ class Child_base : public Genode::Child_policy
_resource_args = args;
try_response_to_resource_request();
}
void exit(int exit_value) override
{
PINF("subsystem \"%s\" exited with value %d", name(), exit_value);
_exited = true;
/* trigger destruction of the child */
Genode::Signal_transmitter(_exit_sig_cap).submit();
}
};
#endif /* _INCLUDE__CLI_MONITOR__CHILD_H_ */

View File

@ -30,7 +30,8 @@ struct Child : Child_base, List<Child>::Element
Genode::Cap_session &cap_session,
Genode::size_t ram_quota,
Genode::size_t ram_limit,
Genode::Signal_context_capability yield_response_sig_cap)
Genode::Signal_context_capability yield_response_sig_cap,
Genode::Signal_context_capability exit_sig_cap)
:
Child_base(ram,
label,
@ -38,7 +39,8 @@ struct Child : Child_base, List<Child>::Element
cap_session,
ram_quota,
ram_limit,
yield_response_sig_cap),
yield_response_sig_cap,
exit_sig_cap),
argument(label, "subsystem")
{ }
};

View File

@ -36,6 +36,8 @@ class Gdb_command_child : public Child
private:
Genode::Signal_context_capability _kill_gdb_sig_cap;
Genode::Signal_context_capability _exit_sig_cap;
Terminal::Session &_terminal;
bool _kill_requested;
@ -56,10 +58,12 @@ class Gdb_command_child : public Child
Genode::size_t ram_limit,
Genode::Signal_context_capability yield_response_sig_cap,
Genode::Signal_context_capability kill_gdb_sig_cap,
Genode::Signal_context_capability exit_sig_cap,
Terminal::Session &terminal)
: Child(ram, label, binary, cap_session, ram_quota, ram_limit,
yield_response_sig_cap),
yield_response_sig_cap, exit_sig_cap),
_kill_gdb_sig_cap(kill_gdb_sig_cap),
_exit_sig_cap(exit_sig_cap),
_terminal(terminal),
_kill_requested(false)
{ }
@ -138,6 +142,7 @@ class Gdb_command : public Command
Subsystem_config_registry &_subsystem_configs;
Signal_context_capability _yield_response_sigh_cap;
Signal_context_capability _kill_gdb_sig_cap;
Signal_context_capability _exit_sig_cap;
/**
* Generate the config node for the GDB subsystem
@ -412,7 +417,7 @@ class Gdb_command : public Command
child = new (Genode::env()->heap())
Gdb_command_child(_ram, label, "init", _cap, ram, ram_limit,
_yield_response_sigh_cap, _kill_gdb_sig_cap,
terminal);
_exit_sig_cap, terminal);
/* configure child */
try {
@ -455,13 +460,15 @@ class Gdb_command : public Command
Gdb_command(Ram &ram, Genode::Cap_session &cap, Child_registry &children,
Subsystem_config_registry &subsustem_configs,
Signal_context_capability yield_response_sigh_cap,
Signal_context_capability kill_gdb_sig_cap)
Signal_context_capability kill_gdb_sig_cap,
Signal_context_capability exit_sig_cap)
:
Command("gdb", "create new subsystem with GDB"),
_ram(ram), _children(children), _cap(cap),
_subsystem_configs(subsustem_configs),
_yield_response_sigh_cap(yield_response_sigh_cap),
_kill_gdb_sig_cap(kill_gdb_sig_cap)
_kill_gdb_sig_cap(kill_gdb_sig_cap),
_exit_sig_cap(exit_sig_cap)
{
add_parameter(new Parameter("--ram", Parameter::NUMBER, "initial RAM quota"));
add_parameter(new Parameter("--ram-limit", Parameter::NUMBER, "limit for expanding RAM quota"));

View File

@ -131,6 +131,10 @@ int main(int argc, char **argv)
static Signal_context_capability kill_gdb_sig_cap =
sig_rec.manage(&kill_gdb_sig_ctx);
static Signal_context exited_child_sig_ctx;
static Signal_context_capability exited_child_sig_cap =
sig_rec.manage(&exited_child_sig_ctx);
static Ram ram(ram_preservation_from_config(),
sig_rec.manage(&yield_broadcast_sig_ctx),
sig_rec.manage(&resource_avail_sig_ctx));
@ -142,10 +146,12 @@ int main(int argc, char **argv)
commands.insert(new Gdb_command(ram, cap, children,
subsystem_config_registry(),
yield_response_sig_cap,
kill_gdb_sig_cap));
kill_gdb_sig_cap,
exited_child_sig_cap));
commands.insert(new Start_command(ram, cap, children,
subsystem_config_registry(),
yield_response_sig_cap));
yield_response_sig_cap,
exited_child_sig_cap));
commands.insert(new Status_command(ram, children));
commands.insert(new Yield_command(children));
commands.insert(new Ram_command(children));
@ -212,6 +218,18 @@ int main(int argc, char **argv)
continue;
}
if (signal.context() == &exited_child_sig_ctx) {
Child *next = nullptr;
for (Child *child = children.first(); child; child = next) {
next = child->next();
if (child->exited()) {
children.remove(child);
Genode::destroy(Genode::env()->heap(), child);
}
}
continue;
}
if (!line_editor.is_complete())
continue;

View File

@ -33,6 +33,7 @@ class Start_command : public Command
Subsystem_config_registry &_subsystem_configs;
List<Argument> _arguments;
Signal_context_capability _yield_response_sigh_cap;
Signal_context_capability _exit_sig_cap;
void _execute_subsystem(char const *name, Command_line &cmd,
Terminal::Session &terminal,
@ -105,7 +106,7 @@ class Start_command : public Command
try {
child = new (Genode::env()->heap())
Child(_ram, label, binary_name, _cap, ram, ram_limit,
_yield_response_sigh_cap);
_yield_response_sigh_cap, _exit_sig_cap);
}
catch (Genode::Rom_connection::Rom_connection_failed) {
tprintf(terminal, "Error: could not obtain ROM module \"%s\"\n",
@ -145,12 +146,14 @@ class Start_command : public Command
Start_command(Ram &ram, Genode::Cap_session &cap, Child_registry &children,
Subsystem_config_registry &subsustem_configs,
Signal_context_capability yield_response_sigh_cap)
Signal_context_capability yield_response_sigh_cap,
Signal_context_capability exit_sig_cap)
:
Command("start", "create new subsystem"),
_ram(ram), _children(children), _cap(cap),
_subsystem_configs(subsustem_configs),
_yield_response_sigh_cap(yield_response_sigh_cap)
_yield_response_sigh_cap(yield_response_sigh_cap),
_exit_sig_cap(exit_sig_cap)
{
add_parameter(new Parameter("--count", Parameter::NUMBER, "number of instances"));
add_parameter(new Parameter("--ram", Parameter::NUMBER, "initial RAM quota"));