Skip to content

Commit

Permalink
init: preserve final state of exited children
Browse files Browse the repository at this point in the history
This is a follow-up patch of "init: avoid too eager child restart". On
each config update of init, init re-applies child-specific configuration
changes. In the case of an already exited child, this re-evaluation
wrongly marked such a child as abandoned because the child's environment
sessions do no longer exist. Abandoning the child, in turn, triggers the
destruction and subseqent restart (because the <start> node of the
configuration still exists). The latter is bad for two reasons.

First, the exit state of the original instance becomes lost. Second, the
restart may have unexpected side effects due to sessions created by the
new instance. I.e., when resizing a partition in sculpt, init would
wrongly restart the gpt-write tool after the tool successfully exited.
This collides with a newly started instance of part_blk/resize2fs, which
now competes with the second gpt-write instance for the exclusive access
of the targeted block device.

The patch prevents init from re-applying configurations to exited
children. The accompanied test case covers the corner case.
  • Loading branch information
nfeske committed Jun 21, 2018
1 parent 2e1e924 commit 9147ddf
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 8 deletions.
86 changes: 79 additions & 7 deletions repos/os/run/init.run
Expand Up @@ -91,6 +91,78 @@ append config {
</expect_init_state>


<message string="exit state handling"/>

<init_config version="exiting child">
<report ids="yes"/>
<parent-provides>
<service name="ROM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="LOG"/>
</parent-provides>
<default caps="100"/>
<start name="exiting">
<binary name="dummy"/>
<resource name="RAM" quantum="2M"/>
<config>
<log string="started"/>
<exit/>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
</init_config>
<expect_log string="[init -> exiting] started"/>
<sleep ms="200"/>
<expect_init_state>
<attribute name="version" value="exiting child"/>
<node name="child">
<attribute name="name" value="exiting"/>
<attribute name="binary" value="dummy"/>
<attribute name="id" value="2"/>
<attribute name="exited" value="0"/>
</node>
</expect_init_state>
<!-- Trigger reconfiguration without changing anything about
the exited application.
The exited application must remain in its 'exited' state. -->
<init_config version="exiting child 2">
<report ids="yes"/>
<parent-provides>
<service name="ROM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="LOG"/>
</parent-provides>
<default caps="100"/>
<start name="exiting">
<binary name="dummy"/>
<resource name="RAM" quantum="2M"/>
<config>
<log string="started"/>
<exit/>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
<start name="unrelated">
<binary name="dummy"/>
<resource name="RAM" quantum="2M"/>
<config/>
<route> <any-service> <parent/> </any-service> </route>
</start>
</init_config>
<sleep ms="200"/>
<expect_init_state>
<attribute name="version" value="exiting child 2"/>
<node name="child">
<attribute name="name" value="exiting"/>
<attribute name="binary" value="dummy"/>
<attribute name="id" value="2"/>
<attribute name="exited" value="0"/>
</node>
</expect_init_state>


<message string="routing to custom log service"/>

<!-- We let the client manually create a LOG session in addition
Expand Down Expand Up @@ -143,11 +215,11 @@ append config {
<expect_init_state>
<node name="child">
<attribute name="name" value="server"/>
<attribute name="id" value="2"/>
<attribute name="id" value="4"/>
</node>
<node name="child">
<attribute name="name" value="client"/>
<attribute name="id" value="4"/>
<attribute name="id" value="6"/>
</node>
</expect_init_state>
<sleep ms="150"/>
Expand Down Expand Up @@ -203,11 +275,11 @@ append config {
<expect_init_state>
<node name="child">
<attribute name="name" value="server"/>
<attribute name="id" value="2"/>
<attribute name="id" value="4"/>
</node>
<node name="child">
<attribute name="name" value="client"/>
<attribute name="id" value="6"/> <!-- client was restarted -->
<attribute name="id" value="8"/> <!-- client was restarted -->
</node>
</expect_init_state>
<sleep ms="100"/>
Expand Down Expand Up @@ -1336,11 +1408,11 @@ append config {
<expect_init_state>
<node name="child">
<attribute name="name" value="server"/>
<attribute name="id" value="23"/>
<attribute name="id" value="25"/>
</node>
<node name="child">
<attribute name="name" value="client"/>
<attribute name="id" value="24"/>
<attribute name="id" value="26"/>
</node>
</expect_init_state>
<sleep ms="150"/>
Expand Down Expand Up @@ -1371,7 +1443,7 @@ append config {
<expect_init_state>
<node name="child">
<attribute name="name" value="client"/>
<attribute name="id" value="25"/>
<attribute name="id" value="27"/>
</node>
</expect_init_state>
<sleep ms="150"/>
Expand Down
6 changes: 6 additions & 0 deletions repos/os/src/app/dummy/main.cc
Expand Up @@ -16,6 +16,7 @@
#include <base/registry.h>
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <base/sleep.h>
#include <root/component.h>
#include <timer_session/connection.h>
#include <log_session/connection.h>
Expand Down Expand Up @@ -333,6 +334,11 @@ struct Dummy::Main

if (node.type() == "log")
log(node.attribute_value("string", String<50>()));

if (node.type() == "exit") {
_env.parent().exit(0);
sleep_forever();
}
});
}

Expand Down
2 changes: 1 addition & 1 deletion repos/os/src/init/child.cc
Expand Up @@ -26,7 +26,7 @@ void Init::Child::destroy_services()
Init::Child::Apply_config_result
Init::Child::apply_config(Xml_node start_node)
{
if (_state == STATE_ABANDONED)
if (_state == STATE_ABANDONED || _exited)
return NO_SIDE_EFFECTS;

/*
Expand Down

0 comments on commit 9147ddf

Please sign in to comment.