next up previous contents
Next: More on the error Up: The Common Package Previous: Comparison routines   Contents

Error handling

      #include <gandalf/common/gan_err.h>
The purpose of the error module is to provide a mechanism by which generic reusable code (typically a software library) can report errors to a variety of applications without the need to modify the library code for each new application context. That is, the error reporting mechanism of the library is highly decoupled from that of the application. Communication of error information from library to application is performed using a small and well defined interface.

The role of the library is to communicate full and unprocessed error information to the application. The role of the application is to access the error information and act on it, whether reporting the error back to the user, ignore it or perform some other action. This demarcation of roles allows the application to use its own error reporting mechanism, without any need to embed application specific code in the library. The library achieves generality because it plays no role in reporting the error information, which usually requires system and application specific facilities. Specifically, the library writes (registers) error information into a LIFO stack (error trace) which is built up as the error unwinds through the nested calls. When the library function called by the application finally returns, with an error code, the application uses an error reporter to access the errors details and processes that information in any way it chooses (e.g. displays an error dialogue box, logs the error in a database).

The library function at which a new error occurs must first flush the error trace before registering the error.

When using the error handling code the following definitions are useful.

Error record: a struct holding error code, file name, line number, and text message for one error.
Error trace: a LIFO stack of error records, which allows temporary storage of error information until defered retrieval by application.
Top record: The most recent error stored in trace.
Error detection: Code that detects occurrence of an error.
Error handling: Action undertaken as a result of detecting an error. In library this typically involves registering the error and returning from current function with an error status. In application this typically involves invoking the reporter function.
Registering: The process of placing an error into the trace
Flushing: The clearing of the error trace
Reporter: A function provided by the application to access error stored in trace and then communicating that information to the user or to a log. The reporter function must then flush the error trace.

To illustrate the use of the error handling package, consider an example application which calls library (Gandalf or other) function A, which itself calls library function B, which has an error that is detected. Function B ``flushes'' the ``error trace'' (because it is the last function called that uses the facilities of the error package), and then ``registers'' the error details into the error trace and unwinds to function A with a return value that indicates an error has occurred. Function A tests the return value and detects the error, and then registers an error into the trace and unwinds to the application with a return value which indicates that an error has occurred. The application tests the return value and detects that an error has occurred, so calls a facility in the error package to report the error. The error report function in turn calls an application-supplied error ``reporter'' function with a pointer to the error trace as an argument. The address of the error trace is stored as a module scoped variable in the error package The reporter accesses the information contained in the error trace using accessor functions, and communicates the error details to the user or to a log in some application specific way (or it may ignore the error or perform some other action).

Consequences and liabilities:

  1. The application is able to:
  2. The library can be used with many applications, without modification.
  3. Interactive resolution of errors occurring in library is problematic. Essentially the library is a black box to the application.

Usage notes for application writer: No code is needed to initialise the error trace. But a error reporting function is optionally installed in the error module using gan_err_set_reporter(). The reporter is an application function of type Gan_ErrorReporterFunc, which is defined in gan_err.h. The reporter must get the error count using gan_err_get_error_count() and then sequentially access the errors stored in the trace using gan_err_get_error(n), where n is the n-th error, and n=1 is the most recent error. If no error reporter is installed, then the error module provides a default reporter gan_err_default_reporter(), whose action is to print the error details into stderr. The function call gan_err_set_reporter(GAN_ERR_DFL) causes the default error reporter to be used, and the call gan_err_set_reporter(GAN_ERR_IGN) inhibits the error reporter from being called. gan_err_set_reporter() returns the address of the error reporter that was replaced so that it can be reinstalled later.

When the application tests the return value of a library function and detects that an error has occurred, it should call gan_err_report() which invokes the error reporter.

The application writer can choose not to buffer the error details in a trace, but instead have the library function report errors immediately, by automatically calling gan_err_report() inside gan_err_register(). No error trace is built up. If the application calls gan_err_report(), no errors are reported because the trace will be empty. Usage of the trace is controlled by gan_err_set_trace() with arguments GAN_ERR_TRACE_ON or GAN_ERR_TRACE_OFF.

Usage notes for library writer: When a error is detected at the deepest function call that uses the facilities of the error module, then gan_err_flush_trace() should be called, followed by gan_err_register(). As the subsequent library function unwinds, they should call gan_err_register() (but not gan_err_flush_trace()), and return with an error code. This continues until the call stack unwinds into the applicaton.

Multi-thread safe: A programmer attempting to use this module in a multithreaded system must heed all precautions attendent with using fully share memory address spaces. To make this module multithread safe, global locks must used to prevent concurrent access to the error trace.

next up previous contents
Next: More on the error Up: The Common Package Previous: Comparison routines   Contents