From a3858bff3ceb461ea80e4063cd317d3923db7855 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Tue, 26 Jun 2018 12:05:31 +0200 Subject: [PATCH] base: handle cancelation of session creation This patch improves the handling of the corner case where a client vanishes while a session request is in flight (CREATE_REQUESTED but not yet AVAILABLE). This corner case could be sporadically observed with the init_loop test on base-linux. In the original version, the session would eventually be delivered but never picked up by anyone. Such a stale session still uses resources that should better be released. In the new version, the parent checks for the liveliness of the client whenever a session is delivered. If there is no client of the session, a close request is immediately issued to the server. The session state must be preserved until the close requests has been answered. --- repos/base/include/base/session_state.h | 2 ++ repos/base/src/lib/base/child.cc | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/repos/base/include/base/session_state.h b/repos/base/include/base/session_state.h index fd8e36cf4..1281a1f41 100644 --- a/repos/base/include/base/session_state.h +++ b/repos/base/include/base/session_state.h @@ -236,6 +236,8 @@ class Genode::Session_state : public Parent::Client, public Parent::Server */ Session::Label client_label() const { return label_from_args(_args.string()); } + bool client_exists() const { return _id_at_client.constructed(); } + /** * Return label presented to the server along with the session request */ diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 6e0f95755..99b74f604 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -644,6 +644,20 @@ void Child::deliver_session_cap(Server::Id id, Session_capability cap) return; } + /* + * If the client vanished during the session creation, the + * session-close state change must be reflected to the server + * as soon as the session becomes available. This enables the + * server to wind down the session. If we just discarded the + * session, the server's ID space would become inconsistent + * with ours. + */ + if (!session.client_exists()) { + session.phase = Session_state::CLOSE_REQUESTED; + session.service().initiate_request(session); + return; + } + session.cap = cap; session.phase = Session_state::AVAILABLE;