sandbox: defer requests for upcoming server

The sandbox library supports the forwarding of session requests from the
outside to one of the hosted children according to a policy. This patch
introduces the distinction between two cases, which previously triggered
the denial of the session request.

- There exists no matching policy for the requested session
- There exists a matching policy but the referred server child
  does not exist (yet)

Whereas the proper response to the first case is the denial of the
request, the second case can occur in situation where a dynamic init is
used to implement a staged startup, for example via the deploy
mechanism. In such cases, a policy may exist as a static rule while the
server has not been started yet. This patch changes the behavior such
that such requests are stalled.

The patch is accompanied with test cases for exercising both situations.

Fixes #3733
This commit is contained in:
Norman Feske 2020-04-21 13:07:55 +02:00
parent f891f4c963
commit f0c4fc1e22
2 changed files with 123 additions and 5 deletions

View File

@ -1203,7 +1203,125 @@
<sleep ms="150"/>
<message string="forward session request to children"/>
<message string="denial of forwarded session request"/>
<init_config version="session forwarding">
<report child_ram="yes" requested="yes"/>
<parent-provides>
<service name="ROM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="LOG"/>
</parent-provides>
<default caps="100"/>
<start name="service_init" caps="200">
<binary name="init"/>
<resource name="RAM" quantum="10M"/>
<provides> <service name="LOG"/> </provides>
<config>
<parent-provides>
<service name="ROM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="LOG"/>
</parent-provides>
<default caps="60"/>
<service name="LOG">
<!-- deny request because no policy matches -->
<policy label="mismatching"> <child name="server"/> </policy>
</service>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
<start name="test">
<binary name="dummy"/>
<resource name="RAM" quantum="4M"/>
<config version="initial">
<create_log_connections count="1" ram_upgrade="3M"/>
<destroy_log_connections/>
</config>
<route>
<service name="LOG"> <child name="service_init"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
</init_config>
<expect_init_state>
<attribute name="version" value="session forwarding"/>
<node name="child">
<attribute name="name" value="test"/>
<attribute name="binary" value="dummy"/>
<node name="requested">
<node name="session">
<attribute name="service" value="LOG"/>
<attribute name="label" value="test"/>
<attribute name="state" value="SERVICE_DENIED"/>
</node>
</node>
</node>
</expect_init_state>
<!-- With the LOG session denied, the 'test' component will remain
in an aborted state. Hence, we have to reset init for the subsequent
good-case tests. -->
<init_config version="empty"> <report/> </init_config>
<expect_init_state>
<attribute name="version" value="empty"/>
</expect_init_state>
<message string="stalled forwarded session request to future server"/>
<init_config version="session forwarding">
<report child_ram="yes"/>
<parent-provides>
<service name="ROM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="LOG"/>
</parent-provides>
<default caps="100"/>
<start name="service_init" caps="200">
<binary name="init"/>
<resource name="RAM" quantum="10M"/>
<provides> <service name="LOG"/> </provides>
<config>
<parent-provides>
<service name="ROM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="LOG"/>
</parent-provides>
<default caps="60"/>
<service name="LOG">
<default-policy> <child name="server"/> </default-policy>
</service>
<!-- server is not yet available -->
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
<start name="test">
<binary name="dummy"/>
<resource name="RAM" quantum="4M"/>
<config version="initial">
<create_log_connections count="1" ram_upgrade="3M"/>
<destroy_log_connections/>
</config>
<route>
<service name="LOG"> <child name="service_init"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
</init_config>
<!-- The 'test' client request is supposed to be stalled, not denied.
Good news, the client will get what it wants pretty soon. -->
<sleep ms="500"/>
<message string="forward session request to child"/>
<init_config>
<report child_ram="yes"/>
@ -1360,11 +1478,11 @@
<expect_init_state>
<node name="child">
<attribute name="name" value="server"/>
<attribute name="id" value="25"/>
<attribute name="id" value="27"/>
</node>
<node name="child">
<attribute name="name" value="client"/>
<attribute name="id" value="26"/>
<attribute name="id" value="28"/>
</node>
</expect_init_state>
<sleep ms="150"/>
@ -1395,7 +1513,7 @@
<expect_init_state>
<node name="child">
<attribute name="name" value="client"/>
<attribute name="id" value="27"/>
<attribute name="id" value="29"/>
</node>
</expect_init_state>
<sleep ms="150"/>

View File

@ -86,7 +86,7 @@ Sandbox::Server::Service::resolve_session_request(Session_label const &label)
match = &service; });
if (!match || match->abandoned())
throw Service_denied();
throw Service_not_present();
return Route { *match, target_label };
}