diff --git a/repos/base/src/core/cpu_session_component.cc b/repos/base/src/core/cpu_session_component.cc index 4e161496a..166743919 100644 --- a/repos/base/src/core/cpu_session_component.cc +++ b/repos/base/src/core/cpu_session_component.cc @@ -283,21 +283,22 @@ Cpu_session_component::~Cpu_session_component() void Cpu_session_component::_deinit_ref_account() { - /* without a ref-account, nothing has do be done */ - if (!_ref) { return; } + /* rewire child ref accounts to this sessions's ref account */ + { + Lock::Guard lock_guard(_ref_members_lock); + for (Cpu_session_component * s; (s = _ref_members.first()); ) { + _unsync_remove_ref_member(*s); + if (_ref) + _ref->_insert_ref_member(s); + } + } - /* give back our remaining quota to our ref account */ - _transfer_quota(*_ref, _quota); + if (_ref) { + /* give back our remaining quota to our ref account */ + _transfer_quota(*_ref, _quota); - /* remove ref-account relation between us and our ref-account */ - Cpu_session_component * const orig_ref = _ref; - _ref->_remove_ref_member(*this); - - /* redirect ref-account relation of ref members to our prior ref account */ - Lock::Guard lock_guard(_ref_members_lock); - for (Cpu_session_component * s; (s = _ref_members.first()); ) { - _unsync_remove_ref_member(*s); - orig_ref->_insert_ref_member(s); + /* remove ref-account relation between us and our ref-account */ + _ref->_remove_ref_member(*this); } } diff --git a/repos/base/src/test/thread/main.cc b/repos/base/src/test/thread/main.cc index 96ebd1ee6..2eef9e3a3 100644 --- a/repos/base/src/test/thread/main.cc +++ b/repos/base/src/test/thread/main.cc @@ -682,6 +682,23 @@ static void test_successive_create_destroy_threads(Env &env) } +/****************************************************** + ** Test destruction of inter-dependent CPU sessions ** + ******************************************************/ + +static void test_destroy_dependent_cpu_sessions(Env &env) +{ + log("destroy dependent CPU sessions in wrong order"); + + Cpu_connection grandchild { env }; + Cpu_connection child { env }; + + grandchild.ref_account(child.rpc_cap()); + + /* when leaving the scope, 'child' is destructed before 'grandchild' */ +} + + void Component::construct(Env &env) { log("--- thread test started ---"); @@ -689,6 +706,9 @@ void Component::construct(Env &env) Attached_rom_dataspace config(env, "config"); try { + + test_destroy_dependent_cpu_sessions(env); + test_stack_alloc(env); test_stack_alignment(env); test_main_thread();