I am trying to start Go application in genode/sel4, 19.08. Now it try to alloc 544Mb Ram (standard initialization approach for reservation via mmap - instead it really alloc space using libc malloc inside mmap() ). So, I have 3 gb ram VM, and ram quota for application is 2 gb.
I see that it just plain hangs on the response in void resource_request(Resource_args const &args), from expanding_parent_client.h
Any suggestions?
here it hang in _wait_for_resource_response: /* * Issue resource request */ Parent_client::resource_request(args);
/* * Block until we get a response for the outstanding resource * request. */ if (_state == BLOCKING_DEFAULT) _wait_for_resource_response(); }
My run script: build { core init timer lib/libc_noux test/go_app }
create_boot_directory
install_config { <config verbose="yes" ld_verbose="yes"> <parent-provides> <service name="ROM"/> <service name="LOG"/> <service name="RM"/> <service name="CPU"/> <service name="PD"/> <service name="IRQ"/> <service name="IO_MEM"/> <service name="IO_PORT"/> </parent-provides> <default-route> <any-service> <any-child/> <parent/> </any-service> </default-route> <default caps="2200"/> <start name="timer"> <resource name="RAM" quantum="1M"/> <provides><service name="Timer"/></provides> </start> <start name="test-go" caps="1500"> <resource name="RAM" quantum="2G"/> <config verbose="yes" ld_verbose="yes" stdin="/null" stdout="/log" stderr="/log"> </config> </start> </config> }
build_boot_image { core init timer ld.lib.so libc.lib.so libm.lib.so posix.lib.so libc_noux.lib.so vfs.lib.so test-go }
Log: ... 2747 MiB RAM and 261141 caps assigned to init Warning: void Genode::Rpc_cap_factory::free(Genode::Native_capability) not implemented - resources leaked: 0x1 Warning: void Genode::Rpc_cap_factory::free(Genode::Native_capability) not implemented - resources leaked: 0x2 [init] 0x40000000 .. 0x4fffffff: stack area [init] 0x30000 .. 0x197fff: ld.lib.so [init] parent provides [init] service "ROM" [init] service "LOG" [init] service "RM" [init] service "CPU" [init] service "PD" [init] service "IRQ" [init] service "IO_MEM" [init] service "IO_PORT" [init] child "timer" [init] RAM quota: 776K [init] cap quota: 2168 [init] ELF binary: timer [init] priority: 0 [init] provides service Timer [init] child "test-go" [init] RAM quota: 2096904K [init] cap quota: 1468 [init] ELF binary: test-go [init] priority: 0 Warning: void Genode::Rpc_cap_factory::free(Genode::Native_capability) not implemented - resources leaked: 0x4
Warning: void Genode::Rpc_cap_factory::free(Genode::Native_capability) not implemented - resources leaked: 0x8 [init -> timer] 0x40000000 .. 0x4fffffff: stack area [init -> timer] 0x30000 .. 0x197fff: ld.lib.so [init] child "timer" announces service "Timer" [init -> test-go] 0x40000000 .. 0x4fffffff: stack area [init -> test-go] 0x30000 .. 0x197fff: ld.lib.so [init -> test-go] 0x12f8000 .. 0x1492fff: libc.lib.so [init -> test-go] 0x1493000 .. 0x1503fff: vfs.lib.so [init -> test-go] 0x1504000 .. 0x153bfff: libm.lib.so [init -> test-go] mmap addr=0xc000000000 len =567472562176 prot=0 flags=4098 libc_fd=-1 offset=0 [init -> test-go] [init -> test-go] resource_request: ram_quota=567472578560
Hello Alexander,
On Thu, Sep 05, 2019 at 11:06:37 CEST, Alexander Tormasov via users wrote:
I am trying to start Go application in genode/sel4, 19.08. Now it try to alloc 544Mb Ram (standard initialization approach for reservation via mmap - instead it really alloc space using libc malloc inside mmap() ). So, I have 3 gb ram VM, and ram quota for application is 2 gb.
[...]
[init -> test-go] mmap addr=0xc000000000 len =567472562176 prot=0 flags=4098 libc_fd=-1 offset=0 [init -> test-go] [init -> test-go] resource_request: ram_quota=567472578560
Those numbers are ~528 GiB, which hints a miscalculation.
Greets
Thank you for pointing out, seems that they really start from such reservation attempt ( 512 << 20 ).
Anyway, system should not hang even if I request 512gb of ram, it should return with error... This is standard approach - we try to alloc until we can, receiving ENOMEM or something similar? Why it is not working?
[init -> test-go] resource_request: ram_quota=567472578560
Those numbers are ~528 GiB, which hints a miscalculation.
Greets
Christian Helmuth Genode Labs
https://www.genode-labs.com/ · https://genode.org/ https://twitter.com/GenodeLabs · /ˈdʒiː.nəʊd/
Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth
Genode users mailing list users@lists.genode.org https://lists.genode.org/listinfo/users
Alexander,
On Thu, Sep 05, 2019 at 11:36:40 CEST, Alexander Tormasov via users wrote:
Thank you for pointing out, seems that they really start from such reservation attempt ( 512 << 20 ).
Let me do the calculation
512 << 20 = 536870912 (bytes)
(512 << 20) / 1024. / 1024 / 1024 = 0.5 (GiB)
As long as "they" do not want to reserve (512 << 20) KiB there must be some miscalculation.
Anyway, system should not hang even if I request 512gb of ram, it should return with error... This is standard approach - we try to alloc until we can, receiving ENOMEM or something similar? Why it is not working?
The current mmap(MAP_ANONYMOUS) implementation seems to strive for satisfaction of the application by not probing the allocation but enforcing it. This ends up in the request for more RAM resources as you traced.
Greets
As long as "they" do not want to reserve (512 << 20) KiB there must be some miscalculation.
Unfortunately, they do want, as explicitly written in the comment -they even try to claim 544gb mem space initially... not real alloc, just reserve .
Anyway, system should not hang even if I request 512gb of ram, it should return with error... This is standard approach - we try to alloc until we can, receiving ENOMEM or something similar? Why it is not working?
The current mmap(MAP_ANONYMOUS) implementation seems to strive for satisfaction of the application by not probing the allocation but enforcing it. This ends up in the request for more RAM resources as you traced.
Yes, but why this call (wait for response from parent) just hangs forever instead of return and say that “I can’t”?
Hi Alexander,
The current mmap(MAP_ANONYMOUS) implementation seems to strive for satisfaction of the application by not probing the allocation but enforcing it. This ends up in the request for more RAM resources as you traced.
Yes, but why this call (wait for response from parent) just hangs forever instead of return and say that “I can’t”?
even though it might be confusing, this is intentional. Let me try to give the rationale.
I'm probably over-generalizing but in Genode, child components are supposed to act according to the parent's wishes. They receive their configuration and a budget of resources from their parent and act accordingly. They should not try to be clever, or probe for resources, or implement fall-backs. That wouldn't be in the interest of the parent. Now if a child is tasked (by its parent) to do a particular job but it has not received enough resources to accomplish it, it _must_ escalate this situation to its parent because the parent is generally the only one who can resolve this situation (e.g., by upgrading the child's resources, or changing plans). If a child silently dealt with a ENOMEM situation without telling the parent, it would deprive the parent from taking a conscious policy decision.
What do we gain from this rigid approach? Simplicity of the components, robustness, and deterministic behavior.
*Simplicity* because the components are relieved from handling error cases, which are - in practice - never thoroughly tested anyway. How many applications are there in the wild who actually handle ENOMEM? How many of those few handle it in a reasonable and deterministic way other than panic? Returning ENOMEM is not a solution because in practice, such rare conditions are not handled. Worse, in traditional software, you find a lot of error-handling code that sits there but is almost never executed or stressed. Such code is the perfect hiding place for vulnerabilities. By relieving software from the this burden, such low-quality code can be omitted.
*Robustness* follows from simplicity and the child being transparent about its problems instead of swallowing them up and failing later with much less obvious symptoms. Failing early is good.
*Deterministic behavior* is reinforced because the child does not implement an opaque policy on its own. In the few cases where an application intents to adapt itself the its resource budgets, Genode allows a component to request its available budgets (Env.pd().avail_ram()) but this is a special case.
---
Regarding your practical problem with the Go runtime, the virtual-memory reservation scheme you encountered is fundamentally at odds with Genode because anonymous memory is always backed by physical memory, not a zero-page mapping and a copy-on-write mechanism as in Linux. This is not a limitation but in line with the philosophy outlined above. A reservation of 500 GiB of memory is in fact an announcement by the application that it may potentially _use_ this memory. The Linux kernel says: fine. So the application proceeds. In the event it actually uses all this memory, the application or even the entire system will suffer in indeterministic and complex ways. Genode does not give such promises. It also does not deny them. Instead, it tells the parent about it so the parent can in principle resolve it. In your case, the parent simply prints a message and keeps the child blocking infinitely.
In your position, I'd try to investigate ways around the reservation-based virtual memory management. We had to overcome similar problems in the past, e.g., I think for the Java runtime. Unfortunately, this usually requires one to dig deep into the runtime. If you get stuck, you may consider making your current working branch publicly available so that others can have a look and possibly provide guidance.
I hope that I could lift the clouds a bit.
Cheers Norman
Hi Norman See below. In short, I understand your ideas -while I have some… can’t say objections, may be suggestions - based on my own experience in industry and academy, including software porting experience.
Yes, but why this call (wait for response from parent) just hangs forever instead of return and say that “I can’t”?
even though it might be confusing, this is intentional. Let me try to give the rationale.
I'm probably over-generalizing but in Genode, child components are supposed to act according to the parent's wishes. They receive their configuration and a budget of resources from their parent and act accordingly. They should not try to be clever, or probe for resources, or implement fall-backs. That wouldn't be in the interest of the parent.
Here I see some contradiction - in our (and most, probably) cases we write child process and software, not parent. I even don’t know who my parent in that case. In normal Unix/Wndows/etc I know that this could be some kind of aux processes provided to me by OS on which I don’t have any power. So, may be it worth to have a separation between «own intentional distributed inside OS (like genode) or over net application childs» and single application as a child of extenrally (not mine!) provided parent?
Now if a child is tasked (by its parent) to do a particular job but it has not received enough resources to accomplish it, it _must_ escalate this situation to its parent because the parent is generally the only one who can resolve this situation (e.g., by upgrading the child's resources, or changing plans). If a child silently dealt with a ENOMEM situation without telling the parent, it would deprive the parent from taking a conscious policy decision.
This all true if this is YOUR parent. But for more generic, «portable» application written in assumption to be able to work in any environment, which does not have any control over parent at all… Technically what you suggest is to drop all code related with «see-adaptation» from such applications. For most of them is a kind of impossible - as you mention, classical example is Java or even Go runtime. These runtime like «OS» themselves intended to work on any environment.
And, my hard believe that any application can’t «just hangs» in any case. At least, in production environment. Even for research/educational ones - I can’t understand why, if I configure system wrongly, it just demonstrate black screen, without any reasonable way to find a reason (can’t attach debugger - not supported on my configuration, and I even don’t know the stack of hanging application/rom module/etc, as it happens with me).
Solution could be, IMHO, 1. Separate 2 cases: your own parent and external parent behavior 2. Implement common mechanism to make a status of parent and myself evaluation, you have everything available, e.g. with dedicated channel to send requests about status of last interactions/etc. May be even make kind of «back signal» like «as a parent, I can’t implement your request and you can commit suicide or do something, not just hang in indefinite wait"
What do we gain from this rigid approach? Simplicity of the components, robustness, and deterministic behavior.
*Simplicity* because the components are relieved from handling error cases, which are - in practice - never thoroughly tested anyway. How many applications are there in the wild who actually handle ENOMEM? How many of those few handle it in a reasonable and deterministic way other than panic? Returning ENOMEM is not a solution because in practice, such rare conditions are not handled. Worse, in traditional software, you find a lot of error-handling code that sits there but is almost never executed or stressed. Such code is the perfect hiding place for vulnerabilities. By relieving software from the this burden, such low-quality code can be omitted.
*Robustness* follows from simplicity and the child being transparent about its problems instead of swallowing them up and failing later with much less obvious symptoms. Failing early is good.
*Deterministic behavior* is reinforced because the child does not implement an opaque policy on its own. In the few cases where an application intents to adapt itself the its resource budgets, Genode allows a component to request its available budgets (Env.pd().avail_ram()) but this is a special case.
I agree with most of arguments, while, as I mentioned above, in real world from engineering point of view we need robots behavior (not just robots system), even for legacy applications. We not always in power of changing old software, so, better to find kind of wrappers not to compromise existent systems, without «indefinite hangs deep inside code due to violation of invisible and non-intenreterable rules" I think that we can find reasonable compromise by adding some agreements, way to report problems, way to debug situations/etc
Eg mentioned Env.pd().avail_ram()) could be used inside allocation mechanism to immediately «in application» report about ENOMEM without escalation to parent.
---
Regarding your practical problem with the Go runtime, the virtual-memory reservation scheme you encountered is fundamentally at odds with Genode because anonymous memory is always backed by physical memory, not a zero-page mapping and a copy-on-write mechanism as in Linux. This is not a limitation but in line with the philosophy outlined above. A reservation of 500 GiB of memory is in fact an announcement by the application that it may potentially _use_ this memory. The Linux kernel says: fine. So the application proceeds. In the event it actually uses all this memory, the application or even the entire system will suffer in indeterministic and complex ways. Genode does not give such promises. It also does not deny them. Instead, it tells the parent about it so the parent can in principle resolve it. In your case, the parent simply
Who are this parent to resolve problem in case of Go environment for ANY Golang applications? Why it will communicate with not mine code (but inside MY application)? I think that this is fundamental question in such approach.
prints a message and keeps the child blocking infinitely.
This is completely wrong, we should not block anything without reasonable diagnostics which can helps people (not copmiler/application/etc) to resolve the situation. Do Genode-on-top-of-microcernel has any tool to debug intentional black screen situation? No-one should be penalized for incorrect code in such a way, IMHO, because this is not constructive approach and do not lead to resolution of problem
In your position, I'd try to investigate ways around the reservation-based virtual memory management. We had to overcome similar problems in the past, e.g., I think for the Java runtime. Unfortunately, this usually requires one to dig deep into the runtime. If you get
I get stuck for some time, now I found some ways, like ask to reserve only 1 gb of ram and try to run everything here, it is somehow supported for mipsle platform. Now I am stuck again in the setting up of signal processing… All these requires efforts in trying to fix runtime code doing some nasty things before even main program. The next potential problem I expect in stack switching (used by go coroutines), and, may be in stack growth (temporary I disable common gcc mechanism from morestack.c). Hope to have soon running helloworld application from go.
Sorry for my spellchecker - found some replacement in the text.
I mean robust, not robot system =) Not see-adaptation - self-adaptation 8-)
Hi Alexander,
our discussion intermingles two topics that should better stay separated.
(A) How to overcome the road block of the Go runtime depending on an mmap feature, which is not available on Genode?
(B) What happens when a component runs out of memory?
Here I see some contradiction - in our (and most, probably) cases we write child process and software, not parent. I even don’t know who my parent in that case. In normal Unix/Wndows/etc I know that this could be some kind of aux processes provided to me by OS on which I don’t have any power. So, may be it worth to have a separation between «own intentional distributed inside OS (like genode) or over net application childs» and single application as a child of extenrally (not mine!) provided parent?
I'm sorry about the confusion. I should have been more specific. Does my reply to Cedric [1] clarify that question?
[1] https://lists.genode.org/pipermail/users/2019-September/006902.html
And, my hard believe that any application can’t «just hangs» in any case. At least, in production environment. Even for research/educational ones - I can’t understand why, if I configure system wrongly, it just demonstrate black screen, without any reasonable way to find a reason (can’t attach debugger - not supported on my configuration, and I even don’t know the stack of hanging application/rom module/etc, as it happens with me).
I agree. I think you got me wrong. I did not want to suggest infinite blocking as an acceptable general solution. But in the static part of the system (the part spawned by the first init instance), resources _are_ statically partitioned. If those static boundaries are violated by one component, the static system ensures that unrelated components are not affected. But it won't magically make the misbehaving component work.
Since there is no general answer to the question of what should happen when a component behaves unexpectedly, the Genode base system does not even try to implement a policy. Instead, it offers a mechanism - the dynamically configurable init I described in my reply to Cedric - that allows you to implement a policy you see fit best.
I get stuck for some time, now I found some ways, like ask to reserve only 1 gb of ram and try to run everything here, it is somehow supported for mipsle platform. Now I am stuck again in the setting up of signal processing… All these requires efforts in trying to fix runtime code doing some nasty things before even main program. The next potential problem I expect in stack switching (used by go coroutines), and, may be in stack growth (temporary I disable common gcc mechanism from morestack.c). Hope to have soon running helloworld application from go.
You spent most of your email discussing topic (B). It's good that you raised the issue, so that Cedric could jump on it, and I had a chance to promote Genode's approach.
However, in the context of your pressing problem at hand (A) and the other nasty technicalities you mentioned above, the discussion of (B) is a distraction, isn't it? It does not help you progressing with (A).
That said, I don't have any magic spell for overcoming (A) unfortunately. Intuitively, I'd try to change the memory-allocation backend of the runtime, just like I stated in my previous posting. But since I haven't looked into the Go runtime myself, I unable to substantiate that.
Cheers Norman
Hi Norman
our discussion intermingles two topics that should better stay separated.
(A) How to overcome the road block of the Go runtime depending on an mmap feature, which is not available on Genode?
(B) What happens when a component runs out of memory?
single application as a child of extenrally (not mine!) provided parent?
I'm sorry about the confusion. I should have been more specific. Does my reply to Cedric [1] clarify that question?
Yes, I assume that for correct work we need something which we can control during code writing. This approach is very close to what I mean. Wile probably one question I still have - if the child, e.g. due to incorrect request to parent, ask for too much resources and wait for response - what to do? As I understand, in current scheme parent should respond something to the child waiting. In that case I still don’t see any clear picture what to do.
In your scheme described in the answer, management component probably is in charge to do something if dynamic init can’t satisfy request… like kill/restart or send some signal to hanging child (I don’t mean unix-like signal, just RPC message if child can accept it). Is it true? What technically can be done in such a case?
That said, I don't have any magic spell for overcoming (A) unfortunately. Intuitively, I'd try to change the memory-allocation backend of the runtime, just like I stated in my previous posting. But since I haven't looked into the Go runtime myself, I unable to substantiate that.
This is complex question, I make some patches and overcome this issue (making initial memory allocation small enough to be able to normally alloc it, seems that runtime can work in this approach for some platforms), so, I can consider (temporary) question A somehow bypassed.
For Question B I received a kind of satisfactory response that I can make better inter-component config scheme which probably will solve my problem with hanging RAM request, while I not yet checked it.
Now I hit another problem with setcontext/getcontext/makecontext/swapcontext family which is not implemented, - probably I need to write separate email thread question about ;-)
Thanks!
Sincerely, Alexander
Howdy list, Norman,
I have a (real world) scenario around those lines, probably a subset / special case of the conversation so far. Discussing it here will help me wrap my head around this aspect of Genode I think:
Let's say you're writing some high-reliability software (take that with a heavy pinch of salt: this is not about airplane embedded software or NPP programs, I'm thinking of humble Radio Automation Software!).
In the radio industry, the 'cardinal sin' is going silent. You don't want your software to stop broadcasting music and go dead for a prolonged time (though crashing and being auto-restarted in a few seconds is tolerated to some degree). Especially if it happens at night when nobody's in the studio to "kick" the computer back into life until the next morning.
If there are no crashing bugs, no automation bugs, and no memory leaks, you're golden -- the above wish is realized.
Focusing on the topic at hand though: what if there is a memory leak that, in Genode's case, ends up as a blocking "resource request", whereby the broadcast app stays there doing nothing, and not being restarted clean from a blank slate ?
Software written against ffmpeg or libav and the like tends to be fussy, and be hard to get 100% right memry wise (ask me how I know *g*). Hopefully that won't be the case on Genode, but let's say it is, for the sake of argument. Let's imagine my app's memory usage creeps up continuously by several MBs per day, such that it eventually overwhelms its assigned memory quota, no matter how generous, after a sufficient amount of time has elapsed.
What is the "Genode doctrine" for dealing with that, for writing highly reliable code ?
To get the discussion started, I'll come up with a few ideas.. Not sure which of these are already implemented/possible in Genode; In my ongoing exploration of the source I've noticed something called "sequence" (?) (I think it's in repos/ports or something) that allows to repeatedly launch a component after it quits, maybe that would help. Anyway here goes:
- init/core (is configured to) kill the child as soon as it oversteps its RAM quota (or capability quota); then restart it, either in lock-step or by another component (sequence?), in order to keep the "init" component as simple as possible.
- the program itself detects that it has gone over-quota, and commits "suicide", then gets restarted (by e.g. "sequence" mentionned above)
- the program implements a hook (callback) for handling quota going over-bound, which simply calls exit(), and "sequence" handles the restarting.
- "sequence" itself is the direct parent (instead of init) of the radio app, and thus is the recipient of ram quota requests, and handles them differently from init: it kills-restarts the app when receiving such a request.
- "sequence" is the direct parent, and monitors the ram usage of its child (say, once per second), because the above method does not work somehow
- other ideas ?
Cedric
Hi Cedric,
great that you are chiming in. Your posting made me realize that I have missed to present a key piece of the puzzle in my reply to Alexander.
In my reply, I emphasized Genode's mantra of decoupling (often complex and potentially flaky) functionality from the policy of what happens when things go wrong. The functionality is the job of a "child" whereas the policy should be in the hands of the "parent". But I left open how the "parent" looks like in practice. You stumbled over the sequence tool, which is actually a good example for a parent. But it is not a good fit for the problem at hand.
The appropriate solution is the use of a dynamically configured init component (let's call it "dynamic init") in tandem with a management component that (1) monitors the state of the dynamic init and its children, and (2) feeds the dynamic init with configurations.
Child ^ | 'state' report Dynamic -------------------> Manager Init <------------------- 'config' ROM
Both the dynamic init and the management component are siblings within another (e.g., the static initial) init instance. The 'state' report and the 'config' ROM are propagated via the report_rom component.
(1) Init supports the reporting of its current state including the state of all children. See [1] for an overview of the reporting options. E.g., in Sculpt, you can have a look at the reported state of the runtime subsystem by looking at /report/runtime/state. The report captures - among other things - the resource consumption of each child. Should a child overstep its resource boundaries, the respective <child> node turns into this
<state> .. <child name="noux-system" ...> <ram ... requested="2M"/> .. </child> </state>
If the 'requested' attribute is present, the child got stuck in a resource request. In the example above, the "noux-system" asks for 2M of additional memory.
[1] https://genode.org/documentation/genode-foundations/19.05/system_configurati...
To resolve this situation, the manager can generate a new configuration for the dynamic init. In particular, it can
- Adjust the resource quota of the resource-starved child. When the dynamic init observes such a configuration change, it answers the resource request and triggers the child to continue.
- Restart the child by incrementing a 'version' attribute of the child node. Once the dynamic init observes a change of this attribute, the child is killed and restarted.
In addition to responding to resource requests, the manager component can also evaluate other parts of the report. The two most interesting bits of information are the exit state of each child (featuring the exit code) and the health. The health is the child's ability to respond to external events. It is described in more detail at [2]. It effectively allows the manager to implement watchdog functionality.
[2] https://genode.org/documentation/genode-foundations/19.05/system_configurati...
Let me stress that in contrast to the child (which implements complex functionality), such a manager component is much less prone to bugs. All it does is consuming reports (parsing some XML) and generating configurations (generating XML). It does not not need any C runtime, file system, or I/O drivers. It can be implemented w/o any dynamic memory allocations. In contrast to the "child", which is expected to be flaky, the "manager" and the dynamic init are supposed to be correct and trustworthy. The functionality of the "dynamic init" is present in the regular "init" component. So the dynamic management does not add new code complexity.
The mechanisms described above are all available right now. Unfortunately, there are no illustrative examples. Thanks to Alexander's and your emails, I realized that this important component-composition pattern is actually missing from the Genode Foundations book. So I will have to do some homework by adding a section. As of now, you may have a look at the init test, which exercises the mechanisms. E.g., the dynamic response to resource requests is tested at [3]. As another - admittedly quite sophisticated - example, the Sculpt manager component [4] plays the role of the manager for the Sculpt system. E.g., it automatically increases the RAM quota of the depot_rom component as needed.
[3] https://github.com/genodelabs/genode/blob/master/repos/os/recipes/raw/test-i... [4] https://github.com/genodelabs/genode/tree/master/repos/gems/src/app/sculpt_m...
- init/core (is configured to) kill the child as soon as it oversteps its RAM quota (or capability quota); then restart it,
either in lock-step or by another component (sequence?), in order to keep the "init" component as simple as possible.
- the program itself detects that it has gone over-quota, and commits "suicide", then gets restarted (by e.g. "sequence"
mentionned above)
- the program implements a hook (callback) for handling quota going over-bound, which simply calls exit(), and
"sequence" handles the restarting.
- "sequence" itself is the direct parent (instead of init) of the radio app, and thus is the recipient of ram quota requests,
and handles them differently from init: it kills-restarts the app when receiving such a request.
- "sequence" is the direct parent, and monitors the ram usage of its child (say, once per second), because the above
method does not work somehow
- other ideas ?
I think all options should be covered by the dynamic init construction described above. The approach can naturally be extended by letting the child "report" additional (higher-level) information about its internal state. The manager may take those reports into account also. E.g., the Sculpt manager consumes the reports generated by drivers and part_block instances to find the Genode partition.
Cedric, could I answer your question?
Cheers Norman
On 9/9/19 6:12 AM, Norman Feske wrote:
Hi Cedric,
great that you are chiming in. Your posting made me realize that I have missed to present a key piece of the puzzle in my reply to Alexander.
[snip]
The mechanisms described above are all available right now. Unfortunately, there are no illustrative examples. Thanks to Alexander's and your emails, I realized that this important component-composition pattern is actually missing from the Genode Foundations book. So I will have to do some homework by adding a section.
In the meantime, a combination of those two messages would make a great Genodians article, if you have time. This is very useful information.
-- John J. Karcher devuser@alternateapproach.com