#include <gandalf/common/gan_err_trace.h>This module implements the error trace used in gan_err.[ch]. The header file would not normally be included explicitly in library or application code. An error trace is a last-in first-out (LIFO) stack for temporarily holding details of multiple error events until an application is ready to read the stack.
The stack is usually flushed by the function in a sequence of nested calls that initially detects an error. As the call stack unwinds the successive functions also register errors, but they should not flush the error trace.
The stack is implemented as a linked list of error records. If in the process of allocating heap memory for a new error record a memory error occurs, then this is refered to as a deep error.
The stack always maintains two preallocated and unused error records for storing the details of the deep error and the error that was in the process of being registered when the deep error occured.
Even if the top of the stack holds a deep error record and the two preallocated records are used, new errors can still be registered into the trace. These attempts may lead to repeated deep errors, in which case the top deep error serves as an indicator of the deep continuing error state. However, if the registration process is successful (because in the intervening time, some external agent has free'd heap memory) the old deep error record is left on the stack and the new errors are registered on top of it.
To ensure that the stack has at least two preallocated records at process startup time, the bottom and second to bottom records of the stack use statically allocated memory. These can never be dynamically free'd.
To do this, an external module must define two static error records. In gan_err.c, this is implemented as:
/* The error trace */ /* Statically allocate last and 2nd to last records for error trace */ static Gan_ErrorTrace record_last = { NULL, GAN_ET_YES, GAN_ET_NO, GAN_ET_YES, NULL, GAN_EC_DFT_SPARE, NULL, 0, NULL }; static Gan_ErrorTrace record_2nd_last = { &record_last, GAN_ET_YES, GAN_ET_NO, GAN_ET_YES, NULL, GAN_EC_DFT_SPARE, NULL, 0, NULL}; /* Address of error trace (i.e. top of LIFO stack) */ static Gan_ErrorTrace * gan_err_trace_top = &record_2nd_last;The symbol gan_et_get_record_first() refers to the current top of stack and is passed into the functions defined in this module as argument 1.
NB. A statically allocated string containing the deep error text message must also exist, but this is defined in gan_err_trace.c.