[net.micro.amiga] Disk Font System BUG!

bobp@amiga.UUCP (Robert S. Pariseau) (12/06/85)

TITLE:Disk Font System BUG!

There is a bug in the V1.0 and V1.1 diskfont.library code that can cause
the system to crash when memory gets low.  A workaround is presented
below.

Disk based system resources such as fonts and device drivers are brought
in to memory when they are first opened.  They remain in memory thereafter
until some task asks for more memory than is available in the system
free memory pool.  At that point the EXEC function AllocMem() "expunges"
(removes from memory) any such resources which currently have zero
openers.  This design means that resources tend to hang around in memory
so that if they are frequently opened and closed there is no time lost
reloading them from the disk.

Many applications periodically use the trick of attempting to AllocMem()
more memory than can possibly be in the system to flush any unused
resources from memory.  Note that if AllocMem() finds any resources to
expunge, then the number returned by AvailMem() AFTER the call to AllocMem()
will be larger than before the call (presuming of course that the
AllocMem() does not, in fact, return a newly allocated chunk of memory
to you).

The bug is that when a disk based font is expunged from memory, the
expunge code in diskfont.library does not properly remove the font
descriptor from the list of fonts known to be in memory.  Thereafter,
whenever a font is looked-up, there is a chance that the system will
crash since the font node now points at memory that has been returned
to the system free pool.

The workaround involves manually removing the font from the font list
before you close it.  The workaround, as presented, provides maximum
protection for the system at the expense of possibly having multiple
copies of the font temporarily exist in memory together.  If you know
that ALL font users in the system are using the workaround, then only
the last closer of the font need do the Remove() function.  Note that
the V1.1 version of Notepad (for instance) does NOT implement this
workaround.

The workaround for the diskfont.library bug is, whenever closing a font:
1)  Forbid();
2)  check the font flags to see if it is a disk font
3)	if a disk font, check that this font is in a list by ensuring that the
	predecessor's and successor's nodes point to it.
4)	    if the font is in a list, Remove(0, font) it.
5)  Permit();
6)  CloseFont();

Note that the first argument to Remove(), the 0, is a dummy argument
present for historical purposes.

The TextFont structure is described in the include file text.h (or text.i
if you speak assembly).  Note that the Accessors field contains the
opener count for a font.

If you are not concerned with reclaiming the memory space taken up by
your unused fonts, it is sufficient, as an alternate workaround, simply
to never close your fonts.  This will insure that AllocMem() never
tries to expunge the font.  Note that this would keep the font from
EVER going away -- even after your program terminates.

If Notepad, or another program, has opened and closed disk fonts prior to
the running of your program, the font list has the potential of
being messed up the next time AllocMem() goes to expunge resources.
If such an expunge has already occurred, there is no recovery other
than to reboot the system.  On the other hand, if an expunge has NOT
yet occurred, you can protect yourself by emptying the font list before
you first trigger an expunge.  To empty the font list, traverse it
starting from the TextFonts pointer found in the structure GfxBase.  Do
a Remove() on each disk based font in the list (WARNING!  Only Remove()
disk based fonts).  The elements of the list are structures of the
type TextFont.  Note that you MUST do this cleanup prior to triggering
your first expunge (i.e., before calling AllocMem() with a large
value).  This cleanup should be done while tasking is disabled (i.e.,
between a Forbid() and a Permit()).

This bug will be fixed in the V1.2 system software.  Any application
implementing the above workaround will continue to work under the new
system software.