mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-18 07:08:18 +00:00
init: close all sessions of exited children
With this patch, init responds to the exit of a child by closing all sessions of the child. E.g., if a child is a GUI application, its nitpicker session is closed at the time of exit, not at the time when the start node disappears from init's configuration. Since this change requires a modification of the 'Genode::Child' class, it takes the chance to make the child-destruction less brutal. The new version ensures that all threads of the destructed subsystem are destructed before other sessions, in particular PD sessions. This eliminates spurious page-fault warnings during the child destruction. On Fiasco.OC, closing the CPU session of a thread while being called by the thread causes a deadlock. Hence, we skip the eager destruction of CPU sessions on this kernel. Related to issue #2659
This commit is contained in:
@ -11,9 +11,13 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/child.h>
|
||||
#include <base/quota_transfer.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/child_policy.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
@ -753,21 +757,44 @@ void Child::initiate_env_sessions()
|
||||
}
|
||||
|
||||
|
||||
Child::Child(Region_map &local_rm,
|
||||
Rpc_entrypoint &entrypoint,
|
||||
Child_policy &policy)
|
||||
:
|
||||
_policy(policy), _local_rm(local_rm), _parent_cap_guard(entrypoint, *this)
|
||||
/**
|
||||
* Return any CPU session that is initiated by the child
|
||||
*
|
||||
* \return client ID of a CPU session, or
|
||||
* client ID 0 if no session exists
|
||||
*/
|
||||
static Parent::Client::Id any_cpu_session_id(Id_space<Parent::Client> const &id_space)
|
||||
{
|
||||
if (_policy.initiate_env_sessions()) {
|
||||
initiate_env_ram_session();
|
||||
initiate_env_sessions();
|
||||
}
|
||||
Parent::Client::Id result { 0 };
|
||||
id_space.for_each<Session_state const>([&] (Session_state const &session) {
|
||||
if (result.value)
|
||||
return;
|
||||
|
||||
bool cpu = (session.service().name() == Cpu_session::service_name());
|
||||
bool env = Parent::Env::session_id(session.id_at_client());
|
||||
|
||||
if (!env && cpu)
|
||||
result = session.id_at_client();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Child::~Child()
|
||||
void Child::close_all_sessions()
|
||||
{
|
||||
/*
|
||||
* Destroy CPU sessions prior to other session types to avoid page-fault
|
||||
* warnings generated by threads that are losing their PD while still
|
||||
* running.
|
||||
*/
|
||||
while (unsigned long id_value = any_cpu_session_id(_id_space).value)
|
||||
close(Parent::Client::Id{id_value});
|
||||
|
||||
_initial_thread.destruct();
|
||||
|
||||
if (KERNEL_SUPPORTS_EAGER_CHILD_DESTRUCTION)
|
||||
_cpu._connection.destruct();
|
||||
|
||||
/*
|
||||
* Purge the meta data about any dangling sessions provided by the child to
|
||||
* other children.
|
||||
@ -809,12 +836,25 @@ Child::~Child()
|
||||
};
|
||||
|
||||
while (_id_space.apply_any<Session_state>(close_fn));
|
||||
|
||||
/*
|
||||
* Make sure to destroy the users of the child's environment sessions
|
||||
* before destructing those sessions.
|
||||
*/
|
||||
_process.destruct();
|
||||
_initial_thread.destruct();
|
||||
}
|
||||
|
||||
|
||||
Child::Child(Region_map &local_rm,
|
||||
Rpc_entrypoint &entrypoint,
|
||||
Child_policy &policy)
|
||||
:
|
||||
_policy(policy), _local_rm(local_rm), _parent_cap_guard(entrypoint, *this)
|
||||
{
|
||||
if (_policy.initiate_env_sessions()) {
|
||||
initiate_env_ram_session();
|
||||
initiate_env_sessions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Child::~Child()
|
||||
{
|
||||
close_all_sessions();
|
||||
_process.destruct();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user