diff --git a/repos/base-foc/src/include/base/internal/child_policy.h b/repos/base-foc/src/include/base/internal/child_policy.h new file mode 100644 index 000000000..cdaf5125f --- /dev/null +++ b/repos/base-foc/src/include/base/internal/child_policy.h @@ -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_ */ diff --git a/repos/base-pistachio/src/include/base/internal/child_policy.h b/repos/base-pistachio/src/include/base/internal/child_policy.h new file mode 100644 index 000000000..98b674bf4 --- /dev/null +++ b/repos/base-pistachio/src/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_ */ diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index df3adfe78..385f1aba1 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -682,6 +682,8 @@ class Genode::Child : protected Rpc_object, 1 /* parent cap */ }; } + void close_all_sessions(); + template void for_each_session(FN const &fn) const { diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 291758ded..54081ae2a 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -242,6 +242,7 @@ _ZN6Genode5Child14session_closedERNS_13Session_stateE T _ZN6Genode5Child14yield_responseEv T _ZN6Genode5Child16resource_requestERKNS_6StringILm160EEE T _ZN6Genode5Child16session_responseENS_8Id_spaceINS_6Parent6ServerEE2IdENS2_16Session_responseE T +_ZN6Genode5Child18close_all_sessionsEv T _ZN6Genode5Child19deliver_session_capENS_8Id_spaceINS_6Parent6ServerEE2IdENS_10CapabilityINS_7SessionEEE T _ZN6Genode5Child19resource_avail_sighENS_10CapabilityINS_14Signal_contextEEE T _ZN6Genode5Child21initiate_env_sessionsEv T diff --git a/repos/base/src/include/base/internal/child_policy.h b/repos/base/src/include/base/internal/child_policy.h new file mode 100644 index 000000000..69468f4c1 --- /dev/null +++ b/repos/base/src/include/base/internal/child_policy.h @@ -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_ */ diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 64c543f35..26faf641f 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -11,9 +11,13 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* Genode includes */ #include #include +/* base-internal includes */ +#include + 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 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) { + 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(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(); } diff --git a/repos/os/src/init/child.h b/repos/os/src/init/child.h index e703c868b..91fc5454c 100644 --- a/repos/os/src/init/child.h +++ b/repos/os/src/init/child.h @@ -547,6 +547,9 @@ class Init::Child : Child_policy, Routed_service::Wakeup */ _exited = true; _exit_value = exit_value; + + _child.close_all_sessions(); + _report_update_trigger.trigger_report_update(); /*