base: consider exception during child construction

This patch make sure that a once managed parent RPC object will always be
dissolved if an exception during the remaining child construction
occurs. The original version would miss the dissolve call if one of the
subsequent members throws an exception at construction time.
This commit is contained in:
Norman Feske 2017-05-13 01:03:59 +02:00 committed by Christian Helmuth
parent 4d3d4ecca0
commit 2c6729768d
3 changed files with 17 additions and 10 deletions

View File

@ -317,8 +317,7 @@ class Genode::Child : protected Rpc_object<Parent>,
Region_map &_local_rm;
Rpc_entrypoint &_entrypoint;
Parent_capability _parent_cap;
Capability_guard _parent_cap_guard;
/* signal handlers registered by the child */
Signal_context_capability _resource_avail_sigh;

View File

@ -265,9 +265,7 @@ class Genode::Rpc_object_base : public Object_pool<Rpc_object_base>::Entry
template <typename RPC_INTERFACE, typename SERVER = RPC_INTERFACE>
struct Genode::Rpc_object : Rpc_object_base, Rpc_dispatcher<RPC_INTERFACE, SERVER>
{
/*****************************
** Server-object interface **
*****************************/
struct Capability_guard;
Rpc_exception_code dispatch(Rpc_opcode opcode, Ipc_unmarshaller &in, Msgbuf_base &out)
{
@ -503,4 +501,17 @@ class Genode::Rpc_entrypoint : Thread, public Object_pool<Rpc_object_base>
void cancel_blocking() { Thread::cancel_blocking(); }
};
template <typename IF, typename SERVER>
struct Genode::Rpc_object<IF, SERVER>::Capability_guard
{
Rpc_entrypoint &_ep;
Rpc_object &_obj;
Capability_guard(Rpc_entrypoint &ep, Rpc_object &obj)
: _ep(ep), _obj(obj) { _ep.manage(&_obj); }
~Capability_guard() { _ep.dissolve(&_obj); }
};
#endif /* _INCLUDE__BASE__RPC_SERVER_H_ */

View File

@ -707,7 +707,7 @@ void Child::_try_construct_env_dependent_members()
_pd.cap(), _pd.session(), _ram.session(),
*_initial_thread, _local_rm,
Child_address_space(_pd.session(), _policy).region_map(),
_parent_cap);
cap());
}
catch (Out_of_ram) { _error("out of RAM during ELF loading"); }
catch (Out_of_caps) { _error("out of caps during ELF loading"); }
@ -757,8 +757,7 @@ Child::Child(Region_map &local_rm,
Rpc_entrypoint &entrypoint,
Child_policy &policy)
:
_policy(policy), _local_rm(local_rm), _entrypoint(entrypoint),
_parent_cap(_entrypoint.manage(this))
_policy(policy), _local_rm(local_rm), _parent_cap_guard(entrypoint, *this)
{
if (_policy.initiate_env_sessions()) {
initiate_env_ram_session();
@ -769,8 +768,6 @@ Child::Child(Region_map &local_rm,
Child::~Child()
{
_entrypoint.dissolve(this);
/*
* Purge the meta data about any dangling sessions provided by the child to
* other children.