base: close PD on 'close_all_sessions'

This patch moves the closing of a child's PD session from the 'Child'
destructor to the 'close_all_sessions' method. This way, the child's
PD quota is immediately returned as soon as init flags a child as
'abandoned', which removes jitter from init's RAM-state reports.

The patch is supposed to make the 'init_loop.run' test much happier.
This commit is contained in:
Norman Feske 2018-06-25 14:55:59 +02:00
parent 1b993714c5
commit ddff89d43e

View File

@ -125,8 +125,11 @@ create_session(Child_policy::Name const &child_name, Service &service,
error(child_name, " requested conflicting session ID ", id, " "
"(service=", service.name(), " args=", args, ")");
id_space.apply<Session_state>(id, [&] (Session_state &session) {
error("existing session: ", session); });
try {
id_space.apply<Session_state>(id, [&] (Session_state &session) {
error("existing session: ", session); });
}
catch (Id_space<Parent::Client>::Unknown_id) { }
}
throw Service_denied();
}
@ -165,7 +168,7 @@ Session_capability Child::session(Parent::Client::Id id,
Parent::Session_args const &args,
Affinity const &affinity)
{
if (!name.valid_string() || !args.valid_string())
if (!name.valid_string() || !args.valid_string() || _pd.closed())
throw Service_denied();
char argbuf[Parent::Session_args::MAX_SIZE];
@ -338,9 +341,13 @@ Parent::Upgrade_result Child::upgrade(Client::Id id, Parent::Upgrade_args const
return UPGRADE_DONE;
}
/* ignore suprious request that may arrive after 'close_all_sessions' */
if (_pd.closed())
return UPGRADE_PENDING;
Upgrade_result result = UPGRADE_PENDING;
_id_space.apply<Session_state>(id, [&] (Session_state &session) {
auto upgrade_session = [&] (Session_state &session) {
if (session.phase != Session_state::CAP_HANDED_OUT) {
warning("attempt to upgrade session in invalid state");
@ -395,7 +402,11 @@ Parent::Upgrade_result Child::upgrade(Client::Id id, Parent::Upgrade_args const
}
session.service().wakeup();
});
};
try { _id_space.apply<Session_state>(id, upgrade_session); }
catch (Id_space<Parent::Client>::Unknown_id) { }
_policy.session_state_changed();
return result;
}
@ -612,7 +623,10 @@ void Child::session_response(Server::Id id, Session_response response)
break;
}
});
} catch (Child_policy::Nonexistent_id_space) { }
}
catch (Child_policy::Nonexistent_id_space) { }
catch (Id_space<Parent::Client>::Unknown_id) {
warning("unexpected session response for unknown session"); }
}
@ -621,6 +635,10 @@ void Child::deliver_session_cap(Server::Id id, Session_capability cap)
try {
_policy.server_id_space().apply<Session_state>(id, [&] (Session_state &session) {
/* ignore responses after 'close_all_sessions' of the client */
if (session.phase != Session_state::CREATE_REQUESTED)
return;
if (session.cap.valid()) {
_error("attempt to assign session cap twice");
return;
@ -632,7 +650,9 @@ void Child::deliver_session_cap(Server::Id id, Session_capability cap)
if (session.ready_callback)
session.ready_callback->session_ready(session);
});
} catch (Child_policy::Nonexistent_id_space) { }
}
catch (Child_policy::Nonexistent_id_space) { }
catch (Id_space<Parent::Client>::Unknown_id) { }
}
@ -854,13 +874,13 @@ void Child::close_all_sessions()
/*
* Issue close requests to the providers of the environment sessions,
* which may be async services. Don't close the PD session since it
* is still needed for reverting session quotas.
* which may be async services.
*/
_log.close();
_binary.close();
if (_linker.constructed())
_linker->close();
_pd.close();
/*
* Remove statically created env sessions from the child's ID space.