From 2c6729768d560aaad5d117108fe0a113f7d3f72b Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Sat, 13 May 2017 01:03:59 +0200 Subject: [PATCH] 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. --- repos/base/include/base/child.h | 3 +-- repos/base/include/base/rpc_server.h | 17 ++++++++++++++--- repos/base/src/lib/base/child.cc | 7 ++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index b0f48255a..afbfb1e27 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -317,8 +317,7 @@ class Genode::Child : protected Rpc_object, 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; diff --git a/repos/base/include/base/rpc_server.h b/repos/base/include/base/rpc_server.h index 822225900..dbe789785 100644 --- a/repos/base/include/base/rpc_server.h +++ b/repos/base/include/base/rpc_server.h @@ -265,9 +265,7 @@ class Genode::Rpc_object_base : public Object_pool::Entry template struct Genode::Rpc_object : Rpc_object_base, Rpc_dispatcher { - /***************************** - ** 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 void cancel_blocking() { Thread::cancel_blocking(); } }; + +template +struct Genode::Rpc_object::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_ */ diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 84bd19877..c709c30cc 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -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.