diff --git a/repos/base/include/base/session_state.h b/repos/base/include/base/session_state.h index fd8e36cf44..1281a1f412 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 6e0f957559..99b74f6048 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;