[Oberon] Safe module unloading (was: Re: Oberon for a C++ user.)

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Sat Oct 8 19:28:55 CEST 2016


Some observations on “safe unloading of modules”, as implemented in Experimental Oberon:

1) One problem I bumped in right away was this: When one closes a viewer in Oberon (say a viewer opened by module Hilbert.Mod), the viewer actually doesn’t disappear from the data structure managed by module Viewers, but continues to exist (as variable Viewers.backup), so that it can be re-opened using the command System.Recall. This means that one cannot in fact unload such modules UNTIL one closes a viewer of *another* module (which simply replaces the backup viewer with the new one, releasing the previous one for the garbage collector). Remedy: I added a procedure Viewes.Flush and a command System.Flush which simply discards the backup viewer (sets it to NIL). —> THEN one can unload the module.

2) This immediately raised another question: In general, unloading is impossible if ANY objects of the module to be unloaded exist anywhere else in the system. In the case of viewers it is of course easy to know what those objects are as one can see them. So the user can just close all open viewers, call System.Flush, then unload the module. Done. But image arbitrary data structures spread over multiple other modules. How can a module possibly keep track of all the objects it has created during its lifetime in main memory, using the “Insert” procedure of third-party modules? So a generic method to find and remove all objects created by a particular module is desirable. Alternatively, it could also be addressed through “finalization" which however is not implemented in Original Oberon, i.e. code that is executed when the module is unloaded (just like BEGIN, there is a CLOSE section in the module’s code). It’s a solvable problem, I just haven’t addressed it.

3) Performance is not an issue at all - even with the “proof of concept” version currently published in procedure System.SecureFree where the mark phase is in fact run twice. It still doesn’t matter. Note that when the algorithm is integrated in the inner core, only 10-15 lines of additional lines of code are needed as the code can be combined with the already existing code, eliminating a lot of code duplication in the process (ps: with the Oberon building tools that are also part of Experimental Oberon it is trivial to create new inner cores and load them onto the disk’s boot block). I have not published the “integrated version” yet because I’m not yet convinced it is in fact the right place to handle this. But it essentially just integrates the existing code into the procedures Kernel.Mark, Kernel.Scan and Modules.Free. It is remarkable that when this is done, the whole thing can be accomplished with only 10-15 lines of additional code and nobody has done it before. But for now, I don’t want to meddle with the inner core - although it would be easy to do.

4) A set of modules that block each other is not really a problem (I think). First, circular module imports are not allowed in Oberon. And when the user creates circular references in dynamic data structures, I consider this a programming error and I’m not responsible for fixing those.

5) If one is really stuck, one can always force the unloading by calling System.Free (or by passing a /f option in the version that is integrated with the inner core). It’s like rm -f in Unix.

6) Regarding the right unloading order, it can usually be found quite easily (manually by taking the inverse of the loading order, or through a process called topological sorting). It would be easy to automate this, but it is not implemented in Experimental Oberon (it’s overkill probably). So the burden is currently on the user.

I’d welcome more input on this topic.. all I wanted to show is that it is *doable* (proof of concept) and that the effort is very small.

Whether it *should* be done is another question. It remains open.

Andreas

--------------------------------------------------------------------------------

chris at gcjd.org 
Sat Oct 8 18:08:30 CEST 2016

On Fri, 7 Oct 2016 00:30:08 +0200, Andreas Pirklbauer wrote:
> Solution #2 ('check for references and don't unload if there are 
> any') is implemented in Experimental Oberon, eliminating inadvertent 
> references to unloaded modules via installed procedures.

Looks very good and not too difficult. Do you have some experience how 
it works in practice? Does the problem occur, that you cannot unload 
and cannot fix it?

My suspicion was, that if you want to unload a set of related modules 
they would block each other. That's why I suggested (yesterday I think) 
to postpone the refusal until reload time, so that you could unload a 
bunch of modules.

Greetings, chris

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.inf.ethz.ch/pipermail/oberon/attachments/20161008/a7e55aaa/attachment.html>


More information about the Oberon mailing list