[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An inconvenient characteristic of some external library functions is to terminate the program rather than returning an error status to the caller for routine events such as a failure of memory allocation. Although in many cases there is no simple workaround for this behavior, memory allocation failures at least can be detected and preventive action taken by using the functions described in this section.
The general approach is to use memory management functions from
‘mwrap.h’ as described previously (Memory leaks), while
additionally registering a return destination for a non-local jump to
be taken in the event of a memory overflow. The jump is taken when an
external library function calls malloc
or realloc
unsuccessfully. The jump avoids passing control back to the library
function, thereby denying it the opportunity to abort, but restores
the context to that of the jump destination almost as if the library
function and all of its intervening callers had returned normally.
The interface is similar to that of the standard setjmp
function defined in the system header file setjmp.h
, and in
fact is built on it, but differs in that the client module does not
explicitly refer to jump buffers. Instead, the mwrap
module
internally maintains a stack of return destinations.
If a jump is taken, it always goes to the most recently registered destination. It may revert to the previously registered destination only when the current one is cleared. This organization provides the necessary flexibility for multiple clients and recursion, but it necessitates a protocol whereby each registration of a destination must be explicitly cleared exactly once.
The following functions implement these two features.
This function specifies the point to which control will pass by a
non-local jump if there is insufficient memory to complete a
subsequent malloc
or realloc
operation. Only the
operations that take place while memory is being managed due to
avm_manage_memory
are affected (Memory leaks).
The function returns zero when it is called normally and successfully registers the return point.
It returns a non-zero value when it has been entered by a non-local
jump (i.e., when malloc
or realloc
has reported
insufficient memory while memory management is active), or when the
return point could not be successfully registered due to insufficient
memory. The client need not distinguish between these two cases,
because both correspond to memory overflows and the destination must
be cleared by avm_clearjmp
regardless.
When a non-zero value is returned due to this function being reached
by a non-local jump, it has the side effects of reclaiming all managed
memory by calling avm_free_managed_memory
and disabling memory
management by calling avm_dont_manage_memory
.
This function cancels the effect of avm_setjmp ()
by preventing
further non-local jumps to its destination if the destination was
successfully registered, or by acknowledging unsuccessful registration
otherwise. It should be called before exiting any function that calls
avm_setjmp ()
or anomalous results may ensue.
The memory management functions avm_manage_memory
and
avm_dont_manage_memory
can be useful with or without
avm_setjmp
, depending on how much of a workaround is needed for
a given library. If a library does not abort on memory overflows,
there is no need to use avm_setjmp
, while it may still be
appropriate to use the other functions against memory leaks.
Calling avm_clearjmp
is particularly important if a client
module with memory management that doesn’t use avm_setjmp
is
invoked subsequently to one that does, so that memory overflows in the
latter won’t cause an attempted jump to a stale destination.
A further complication that arises from careful consideration of these
issues is the situation of a client module that does not intend to use
avm_setjmp
but is called (perhaps indirectly) by one that
does. The latter will have registered a return destination that
remains active and valid even if the former refrains from doing so,
thereby allowing a branch to be taken that should have been prevented.
Although it is an unusual situation, it can be accommodated by the
following function.
This function temporarily inhibits non-local jumps to destinations
previously registered by avm_setjmp
until the next time
avm_clearjmp
is called. Thereafter, any previously registered
destinations are reinstated.
A sketch of how some of these functions might be used to cope with
library functions that would otherwise terminate the program in the
event of a memory overflow is shown below. The GNU libc
reference manual contains a related discussion of non-local jumps.
#include <avm/mwrap.h> ... int function foobar (foo, bar) ... { char *my_data; my_data = (char *) malloc (100); if (avm_setjmp () != 0) { avm_clearjmp (); avm_turn_on_stdout (); /* reaching here */ free (my_data); /* means malloc */ return ABNORMAL_STATUS; /* failed below */ } avm_turn_off_stdout (); avm_manage_memory (); ... call_library_functions (foo, bar); /* may jump */ ... /* to above */ avm_free_managed_memory (); avm_turn_on_stdout (); avm_clearjmp (); free (my_data); /* reaching here means */ return OK_STATUS; /* jumping wasn't done */ } |
Portability issues with these functions are not well known at this
writing. If the configuration script for avram
fails to detect
the required features in setjmp.h
on the host system,
conditional compilation directives will disable the functions
avm_setjmp
, avm_clearjmp
, and avm_setnonjmp
.
However, it may still be possible for the other avm_
* memory
management functions to be configured.
If setjmp
is not configured, the avm_setjmp
function
is still callable but will always return a value of zero, and will
provide no protection against external library functions aborting the
program. The other two will perform no operation and return.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on November 8, 2012 using texi2html 1.82.