base: handle dangling env sessions in ~Child

This commit addresses the situation where an environment session
outlives the session-providing service. In this case, the env session
got already invaidated at the destruction time of the server. However,
the underlying session-state structure continues to exist until the
client is destructed. During the eventual destruction of such a dangling
environment session, we have to be careful not to interact with the
no-longer existing service.

Ref #2197
This commit is contained in:
Norman Feske 2017-01-18 13:47:17 +01:00
parent 21458e6efa
commit e43da51bd6
3 changed files with 26 additions and 9 deletions

View File

@ -467,6 +467,8 @@ class Genode::Child : protected Rpc_object<Parent>,
void _revert_quota_and_destroy(Session_state &);
void _discard_env_session(Id_space<Parent::Client>::Id);
Close_result _close(Session_state &);
/**

View File

@ -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<Parent::Client>::Id id)
{
auto discard_id_fn = [&] (Session_state &s) { s.discard_id_at_client(); };
try { _id_space.apply<Session_state>(id, discard_id_fn); }
catch (Id_space<Parent::Client>::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<Session_state>(Env::ram(), discard_id_fn);
_id_space.apply<Session_state>(Env::cpu(), discard_id_fn);
_id_space.apply<Session_state>(Env::pd(), discard_id_fn);
_id_space.apply<Session_state>(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.

View File

@ -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);
}