[mod.computers.apollo] trapping a full disk

mishkin@EDDIE.MIT.EDU@apollo.UUCP (12/04/86)

    I have a program which consumes massive amounts of dynamic memory.
    The inevitable problem is that the disk fills up and the program
    stops.  It seems the new and rws_$alloc procedures don't detect that
    the disk is full.  The fault occurs when the pointer is dereferenced.
    I have been able to trap this fault, but I haven't been able to do
    anything about it.  When I dispose of some memory and return from
    the fault handler with the  value pfm_$return_to_faulting_code the
    process dies without a clue as to what happened.

I'm afraid there's no very nice way to deal with this problem.  The problem
is equivalent to the "out of swap space" problem on other operating
systems.  On the Apollo however, the disk(s) are not divided into swap
areas and filesystem areas.  There are only filesystem areas (and generally
only one of them per disk).

The reason "rws_$alloc" doesn't return an error is because it is layered
on top of the virtual memory mapping primitives.  When one maps some
non-yet-existing pages of a file (e.g. pages past the current "EOF"),
the pages are not actually allocated on the disk until the virtual
addresses corresponding to the pages are accessed.  "rws_$alloc" does
not access those addresses, so the client of "rws_$alloc" (i.e. the code
that uses the returned pointer) is the first acccessor (and hence the
one that causes the disk-full fault).

The reason catching the fault didn't work is because the disk-full fault
is "not continuable".

At some future release, this problem will probably be dealt with by making
RWS ensure that the disk pages are there to back the virtual memory it's
allocating.  Until then, you can work around the problem by doing something
like:

    char *my_alloc(len)
    int len;
    {
        char *p, *q;
        status_$t st, fst;
        pfm_$cleanup_rec crec;

        /*
         * Allocate the storage.
         */

        p = rws_$alloc_heap_pool(rws_$std_pool, len);
    
        if (p == 0)
            return (p);

        /*
         * Loop over the storage, touching it to cause the disk pages to be
         * allocated.  Note we set up a cleanup handler to catch disk-full
         * faults.
         */

        fst = pfm_$cleanup(crec);
        if (fst.all != pfm_$cleanup_set) {
            rws_$release_heap_pool(p, rws_$std_pool, st);
            pfm_$enable();
            return ((char *) 0);
        }
    
        for (q = p; q < p + len; q += 1024)
            *q = 0;
    
        pfm_$rls_cleanup(crec, st);

        return (p);
    }

Note that, unfortunately, the disk space backing RWS space is not freed
until the program returns.  I.e. calling "rws_$release_heap..." will NOT
immediately result in disk space being made available.  However, it will
make the RWS space available for other uses.  This scheme also should
keep the process from dying mysteriously.

We know this is a problem.

                -- Nat Mishkin
                   Apollo Computer Inc.
                   mishkin@apollo.uucp
-------