Feedback on 23.05

Norman Feske norman.feske at genode-labs.com
Wed Jul 26 11:14:28 CEST 2023


Hi Cedrik,

regarding your question 2, you did a good job with exploring the 
options. Let me try to fill out the few missing pieces of the picture.

On 2023-07-25 21:08, ttcoder at netcourrier.com wrote:
> 2) Launching apps
> A newbie question ! (yes even after 5 years I still have those :-)
> How to launch components (applications).
> Grepping through the Genode repo, I came up with:
> 
> - use a sub init with a generous RAM alotment (2 GB), and drive its config ROM through a report_rom:
> a list of launched apps has to be maintained by a "third actor" (not the sub-init, and not any of
> the client apps that require launching a process, but rather some sort of stand-by "registrar"), and
> its job would be to re-generate the sub's config ROM whenever that list grows as a new app is launched.
> Problem is, what happens when the user *quits* an application ? When that occurs, the app is still
> part of the sub-init's config, so next time sub reads its config, it's going to re-launch it, right ?
> This would otherwise seem to fit the bill well, if not for that problem of un-desired app relaunch.
> Maybe I can solve that problem by sending notifications every time an app is quit (if it's quit cleanly
> rather than crashing, at least), and the notification recipient (probably the "registrar" ?)
> would remove the relevant snippet from the sub-init's config.

This is generally the most advised option. It is promoted in the 
"Foundations" book [1], and is prominently employed by Sculpt's 
Leitzentrale UI.

[1] 
https://genode.org/documentation/genode-foundations/23.05/components/Component_composition.html#Feedback_control_system

The re-use of the regular init component relieves you from low-level 
technicalities like the child-component creation via Genode's low-level 
C++ API, the parent-child protocol, or the routing of sessions. As the 
approach is solely based on exchanging plain text (XML) between the 
dynamic init instance and the manager, a manager could in principle be 
written in any programming language that is able to handle XML.

You apparently just missed one little detail, which is the "state" 
report generated by init. Whenever something interesting happens (e.g., 
a child exits), init reflects this information in an updated state 
report, which can then be inspected by the management component 
("registrar") to take action, like removing the <start> node from the 
init config when spotting an 'exited="yes"' attribute for a child. The 
level of detail of the state report is configurable. One can go as far 
as letting init list all sessions used by each child, which gives the 
"registrar" deep insights into the interplay and state of the hosted 
components.

As an experiment, in Sculpt you can peek into the state report of the 
runtime init by looking at /report/runtime/state using Vim in the 
inspect view. After adding the attribute 'requested="yes"' to the 
<report> node of /config/managed/runtime, the state report becomes much 
more detailed.

For forcibly re-starting a component, the "registrar" can make use of 
the 'version' attribute of the <start> node. Whenever the version is 
changed, init replaces the existing component by a new instance. This is 
what happens when pressing a "Restart" button for a component in Sculpt.

> - loader_session: seems close enough too, and simplier to use, but the README says the ram/caps of the created child
> will be substracted from the caller, instead of from the launcher (i.e. the opposite of a sub-init).
> But I want to do the reverse.

The loader session is a relic, which will eventually be removed.

> - fork/exec from libc : same as launcher_session, but seemingly with the (additional) awkwardness of old-style UNIX,
> where fork() creates a full duplicate of the caller, at least until exec() is called
> (so the caller app would need to have twice as much ram/caps as it needs, even if it just spawns
> something tiny like /bin/ls !).

The fork/exec mechanism is nice as a bridging solution to host existing 
POSIX software. But it cannot give you the flexibility and level of 
control that Genode offers. E.g., when spawning a child using fork, the 
child's resource allocations are not capped but paid for by the parent.

> - sandbox.h : couldn't find a "tutorial" style usage of it via grep
> -r sandbox repos/, but maybe I should dive right in and experiment
> until I understand the gist of it, using the more complex use-cases
> in the repos ?
The sandbox library covers use cases where the dynamic init approach is 
not flexible enough. The library is actually the same code as used by 
init internally. By using this library, one can create custom 
incarnations of init that provide local services to the hosted children.

These cases are rare but they exist. E.g., the (emerging) debug monitor 
[2] uses the sandbox library to intercept Genode's low-level services 
used by the hosted children. Another example is a GUI application that 
wants to use a 'menu_view' as a child component and needs to intercept 
the menu_view's interplay with the GUI server, e.g., to get hold of 
keyboard input [3].

[2] https://github.com/genodelabs/genode/tree/master/repos/os/src/monitor
[3] 
https://github.com/genodelabs/genode/tree/master/repos/gems/src/app/text_area

In short, I recommend taking the dynamic-init approach. Should you 
encounter its limitations, switch to the sandbox library. Better don't 
touch the low-level C++ APIs like 'base/child.h'. Please ignore the 
loader session.

Cheers
Norman

-- 
Dr.-Ing. Norman Feske
Genode Labs

https://www.genode-labs.com · https://genode.org

Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden
Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth




More information about the users mailing list