diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index 5100891c0..f72ff75df 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -467,6 +467,8 @@ class Genode::Child : protected Rpc_object, void _revert_quota_and_destroy(Session_state &); + void _discard_env_session(Id_space::Id); + Close_result _close(Session_state &); /** diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index f09aef263..05406687c 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -620,9 +620,18 @@ void Child::_try_construct_env_dependent_members() } -Child::Child(Region_map &local_rm, - Rpc_entrypoint &entrypoint, - Child_policy &policy) +void Child::_discard_env_session(Id_space::Id id) +{ + auto discard_id_fn = [&] (Session_state &s) { s.discard_id_at_client(); }; + + try { _id_space.apply(id, discard_id_fn); } + catch (Id_space::Unknown_id) { } +} + + +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)) @@ -668,12 +677,10 @@ Child::~Child() /* * Remove statically created env sessions from the child's ID space. */ - auto discard_id_fn = [&] (Session_state &s) { s.discard_id_at_client(); }; - - _id_space.apply(Env::ram(), discard_id_fn); - _id_space.apply(Env::cpu(), discard_id_fn); - _id_space.apply(Env::pd(), discard_id_fn); - _id_space.apply(Env::log(), discard_id_fn); + _discard_env_session(Env::ram()); + _discard_env_session(Env::cpu()); + _discard_env_session(Env::pd()); + _discard_env_session(Env::log()); /* * Remove dynamically created sessions from the child's ID space. diff --git a/repos/base/src/lib/base/session_state.cc b/repos/base/src/lib/base/session_state.cc index 79203e93b..3ad564cc1 100644 --- a/repos/base/src/lib/base/session_state.cc +++ b/repos/base/src/lib/base/session_state.cc @@ -94,6 +94,14 @@ void Session_state::destroy() */ id_at_server.destruct(); + /* + * Make sure that the session does not appear as being alive. I.e., if + * 'destroy' was called during the destruction of a service, prevent the + * 'Local_connection' destructor of a dangling session to initiate a close + * request to the no-longer existing service. + */ + phase = CLOSED; + if (_factory) _factory->_destroy(*this); }