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:
parent
47b11bf9b7
commit
e0e9b3b32e
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* \brief Hook for kernel-specific child-handling policy
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2018-01-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_
|
||||||
|
#define _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_
|
||||||
|
|
||||||
|
namespace Genode {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On Fiasco.OC, we cannot eagerly destroy the CPU session of a child
|
||||||
|
* as a direct response of a 'Parent::exit' RPC call. The parent gets
|
||||||
|
* stuck at the CPU-session destruction, which is unexpected. By setting
|
||||||
|
* the constant below to 'false', we work around the problem.
|
||||||
|
*
|
||||||
|
* See https://github.com/genodelabs/genode/issues/2659
|
||||||
|
*/
|
||||||
|
constexpr bool KERNEL_SUPPORTS_EAGER_CHILD_DESTRUCTION = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_ */
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* \brief Hook for kernel-specific child-handling policy
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2018-01-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_
|
||||||
|
#define _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_
|
||||||
|
|
||||||
|
namespace Genode {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On L4/Pistachio, the attempt to eagerly destroy the CPU session of a
|
||||||
|
* child as a direct response of a 'Parent::exit' RPC call results in a
|
||||||
|
* kernel assertion. Since the kernel is abandoned, this issue will most
|
||||||
|
* likely remain unfixed.
|
||||||
|
*
|
||||||
|
* See https://github.com/genodelabs/genode/issues/2659 for a discussion
|
||||||
|
* of a related problem.
|
||||||
|
*/
|
||||||
|
constexpr bool KERNEL_SUPPORTS_EAGER_CHILD_DESTRUCTION = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_ */
|
|
@ -682,6 +682,8 @@ class Genode::Child : protected Rpc_object<Parent>,
|
||||||
1 /* parent cap */ };
|
1 /* parent cap */ };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void close_all_sessions();
|
||||||
|
|
||||||
template <typename FN>
|
template <typename FN>
|
||||||
void for_each_session(FN const &fn) const
|
void for_each_session(FN const &fn) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -242,6 +242,7 @@ _ZN6Genode5Child14session_closedERNS_13Session_stateE T
|
||||||
_ZN6Genode5Child14yield_responseEv T
|
_ZN6Genode5Child14yield_responseEv T
|
||||||
_ZN6Genode5Child16resource_requestERKNS_6StringILm160EEE T
|
_ZN6Genode5Child16resource_requestERKNS_6StringILm160EEE T
|
||||||
_ZN6Genode5Child16session_responseENS_8Id_spaceINS_6Parent6ServerEE2IdENS2_16Session_responseE T
|
_ZN6Genode5Child16session_responseENS_8Id_spaceINS_6Parent6ServerEE2IdENS2_16Session_responseE T
|
||||||
|
_ZN6Genode5Child18close_all_sessionsEv T
|
||||||
_ZN6Genode5Child19deliver_session_capENS_8Id_spaceINS_6Parent6ServerEE2IdENS_10CapabilityINS_7SessionEEE T
|
_ZN6Genode5Child19deliver_session_capENS_8Id_spaceINS_6Parent6ServerEE2IdENS_10CapabilityINS_7SessionEEE T
|
||||||
_ZN6Genode5Child19resource_avail_sighENS_10CapabilityINS_14Signal_contextEEE T
|
_ZN6Genode5Child19resource_avail_sighENS_10CapabilityINS_14Signal_contextEEE T
|
||||||
_ZN6Genode5Child21initiate_env_sessionsEv T
|
_ZN6Genode5Child21initiate_env_sessionsEv T
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* \brief Hook for kernel-specific child-handling policy
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2018-01-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_
|
||||||
|
#define _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_
|
||||||
|
|
||||||
|
namespace Genode { constexpr bool KERNEL_SUPPORTS_EAGER_CHILD_DESTRUCTION = true; }
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__BASE__INTERNAL__CHILD_POLICY_H_ */
|
|
@ -11,9 +11,13 @@
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/child.h>
|
#include <base/child.h>
|
||||||
#include <base/quota_transfer.h>
|
#include <base/quota_transfer.h>
|
||||||
|
|
||||||
|
/* base-internal includes */
|
||||||
|
#include <base/internal/child_policy.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
|
@ -753,21 +757,44 @@ void Child::initiate_env_sessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Child::Child(Region_map &local_rm,
|
/**
|
||||||
Rpc_entrypoint &entrypoint,
|
* Return any CPU session that is initiated by the child
|
||||||
Child_policy &policy)
|
*
|
||||||
:
|
* \return client ID of a CPU session, or
|
||||||
_policy(policy), _local_rm(local_rm), _parent_cap_guard(entrypoint, *this)
|
* 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()) {
|
Parent::Client::Id result { 0 };
|
||||||
initiate_env_ram_session();
|
id_space.for_each<Session_state const>([&] (Session_state const &session) {
|
||||||
initiate_env_sessions();
|
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
|
* Purge the meta data about any dangling sessions provided by the child to
|
||||||
* other children.
|
* other children.
|
||||||
|
@ -809,12 +836,25 @@ Child::~Child()
|
||||||
};
|
};
|
||||||
|
|
||||||
while (_id_space.apply_any<Session_state>(close_fn));
|
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.
|
Child::Child(Region_map &local_rm,
|
||||||
*/
|
Rpc_entrypoint &entrypoint,
|
||||||
_process.destruct();
|
Child_policy &policy)
|
||||||
_initial_thread.destruct();
|
:
|
||||||
|
_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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -547,6 +547,9 @@ class Init::Child : Child_policy, Routed_service::Wakeup
|
||||||
*/
|
*/
|
||||||
_exited = true;
|
_exited = true;
|
||||||
_exit_value = exit_value;
|
_exit_value = exit_value;
|
||||||
|
|
||||||
|
_child.close_all_sessions();
|
||||||
|
|
||||||
_report_update_trigger.trigger_report_update();
|
_report_update_trigger.trigger_report_update();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue