Blame doc/err.rst

Packit 67cb25
.. index:: error handling
Packit 67cb25
Packit 67cb25
**************
Packit 67cb25
Error Handling
Packit 67cb25
**************
Packit 67cb25
Packit 67cb25
This chapter describes the way that GSL functions report and handle
Packit 67cb25
errors.  By examining the status information returned by every function
Packit 67cb25
you can determine whether it succeeded or failed, and if it failed you
Packit 67cb25
can find out what the precise cause of failure was.  You can also define
Packit 67cb25
your own error handling functions to modify the default behavior of the
Packit 67cb25
library.
Packit 67cb25
Packit 67cb25
The functions described in this section are declared in the header file
Packit 67cb25
:file:`gsl_errno.h`.
Packit 67cb25
Packit 67cb25
Error Reporting
Packit 67cb25
===============
Packit 67cb25
Packit 67cb25
The library follows the thread-safe error reporting conventions of the
Packit 67cb25
POSIX Threads library.  Functions return a non-zero error code to
Packit 67cb25
indicate an error and :code:`0` to indicate success::
Packit 67cb25
Packit 67cb25
    int status = gsl_function (...)
Packit 67cb25
Packit 67cb25
    if (status) { /* an error occurred */
Packit 67cb25
      .....       
Packit 67cb25
      /* status value specifies the type of error */
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
The routines report an error whenever they cannot perform the task
Packit 67cb25
requested of them.  For example, a root-finding function would return a
Packit 67cb25
non-zero error code if could not converge to the requested accuracy, or
Packit 67cb25
exceeded a limit on the number of iterations.  Situations like this are
Packit 67cb25
a normal occurrence when using any mathematical library and you should
Packit 67cb25
check the return status of the functions that you call.
Packit 67cb25
Packit 67cb25
Whenever a routine reports an error the return value specifies the type
Packit 67cb25
of error.  The return value is analogous to the value of the variable
Packit 67cb25
:code:`errno` in the C library.  The caller can examine the return code
Packit 67cb25
and decide what action to take, including ignoring the error if it is
Packit 67cb25
not considered serious.
Packit 67cb25
Packit 67cb25
In addition to reporting errors by return codes the library also has an
Packit 67cb25
error handler function :func:`gsl_error`.  This function is called by
Packit 67cb25
other library functions when they report an error, just before they
Packit 67cb25
return to the caller.  The default behavior of the error handler is to
Packit 67cb25
print a message and abort the program::
Packit 67cb25
Packit 67cb25
    gsl: file.c:67: ERROR: invalid argument supplied by user
Packit 67cb25
    Default GSL error handler invoked.
Packit 67cb25
    Aborted
Packit 67cb25
Packit 67cb25
The purpose of the :func:`gsl_error` handler is to provide a function
Packit 67cb25
where a breakpoint can be set that will catch library errors when
Packit 67cb25
running under the debugger.  It is not intended for use in production
Packit 67cb25
programs, which should handle any errors using the return codes.
Packit 67cb25
Packit 67cb25
.. index::
Packit 67cb25
   single: error codes, reserved
Packit 67cb25
Packit 67cb25
Error Codes
Packit 67cb25
===========
Packit 67cb25
Packit 67cb25
The error code numbers returned by library functions are defined in
Packit 67cb25
the file :file:`gsl_errno.h`.  They all have the prefix :code:`GSL_` and
Packit 67cb25
expand to non-zero constant integer values. Error codes above 1024 are
Packit 67cb25
reserved for applications, and are not used by the library.  Many of
Packit 67cb25
the error codes use the same base name as the corresponding error code
Packit 67cb25
in the C library.  Here are some of the most common error codes,
Packit 67cb25
Packit 67cb25
.. index::
Packit 67cb25
   single: error codes
Packit 67cb25
Packit 67cb25
.. var:: int GSL_EDOM
Packit 67cb25
Packit 67cb25
   Domain error; used by mathematical functions when an argument value does
Packit 67cb25
   not fall into the domain over which the function is defined (like
Packit 67cb25
   :data:`EDOM` in the C library)
Packit 67cb25
Packit 67cb25
.. var:: int GSL_ERANGE
Packit 67cb25
Packit 67cb25
   Range error; used by mathematical functions when the result value is not
Packit 67cb25
   representable because of overflow or underflow (like :data:`ERANGE` in the C
Packit 67cb25
   library)
Packit 67cb25
Packit 67cb25
.. var:: int GSL_ENOMEM
Packit 67cb25
Packit 67cb25
   No memory available.  The system cannot allocate more virtual memory
Packit 67cb25
   because its capacity is full (like :data:`ENOMEM` in the C library).  This error
Packit 67cb25
   is reported when a GSL routine encounters problems when trying to
Packit 67cb25
   allocate memory with :func:`malloc`.
Packit 67cb25
Packit 67cb25
.. var:: int GSL_EINVAL
Packit 67cb25
Packit 67cb25
   Invalid argument.  This is used to indicate various kinds of problems
Packit 67cb25
   with passing the wrong argument to a library function (like :data:`EINVAL` in the C
Packit 67cb25
   library). 
Packit 67cb25
Packit 67cb25
The error codes can be converted into an error message using the
Packit 67cb25
function :func:`gsl_strerror`.
Packit 67cb25
Packit 67cb25
.. function:: const char * gsl_strerror (const int gsl_errno)
Packit 67cb25
Packit 67cb25
   This function returns a pointer to a string describing the error code
Packit 67cb25
   :data:`gsl_errno`. For example::
Packit 67cb25
Packit 67cb25
     printf ("error: %s\n", gsl_strerror (status));
Packit 67cb25
Packit 67cb25
   would print an error message like :code:`error: output range error` for a
Packit 67cb25
   status value of :data:`GSL_ERANGE`.
Packit 67cb25
Packit 67cb25
.. index:: error handlers
Packit 67cb25
Packit 67cb25
Error Handlers
Packit 67cb25
==============
Packit 67cb25
Packit 67cb25
The default behavior of the GSL error handler is to print a short
Packit 67cb25
message and call :func:`abort`.  When this default is in use programs
Packit 67cb25
will stop with a core-dump whenever a library routine reports an error.
Packit 67cb25
This is intended as a fail-safe default for programs which do not check
Packit 67cb25
the return status of library routines (we don't encourage you to write
Packit 67cb25
programs this way).
Packit 67cb25
Packit 67cb25
If you turn off the default error handler it is your responsibility to
Packit 67cb25
check the return values of routines and handle them yourself.  You can
Packit 67cb25
also customize the error behavior by providing a new error handler. For
Packit 67cb25
example, an alternative error handler could log all errors to a file,
Packit 67cb25
ignore certain error conditions (such as underflows), or start the
Packit 67cb25
debugger and attach it to the current process when an error occurs.
Packit 67cb25
Packit 67cb25
All GSL error handlers have the type :code:`gsl_error_handler_t`, which is
Packit 67cb25
defined in :file:`gsl_errno.h`,
Packit 67cb25
Packit 67cb25
.. type:: gsl_error_handler_t
Packit 67cb25
Packit 67cb25
   This is the type of GSL error handler functions.  An error handler will
Packit 67cb25
   be passed four arguments which specify the reason for the error (a
Packit 67cb25
   string), the name of the source file in which it occurred (also a
Packit 67cb25
   string), the line number in that file (an integer) and the error number
Packit 67cb25
   (an integer).  The source file and line number are set at compile time
Packit 67cb25
   using the :code:`__FILE__` and :code:`__LINE__` directives in the
Packit 67cb25
   preprocessor.  An error handler function returns type :code:`void`.
Packit 67cb25
   Error handler functions should be defined like this::
Packit 67cb25
Packit 67cb25
     void handler (const char * reason, 
Packit 67cb25
                   const char * file, 
Packit 67cb25
                   int line, 
Packit 67cb25
                   int gsl_errno)
Packit 67cb25
Packit 67cb25
To request the use of your own error handler you need to call the
Packit 67cb25
function :func:`gsl_set_error_handler` which is also declared in
Packit 67cb25
:file:`gsl_errno.h`,
Packit 67cb25
Packit 67cb25
.. function:: gsl_error_handler_t * gsl_set_error_handler (gsl_error_handler_t * new_handler)
Packit 67cb25
Packit 67cb25
   This function sets a new error handler, :data:`new_handler`, for the GSL
Packit 67cb25
   library routines.  The previous handler is returned (so that you can
Packit 67cb25
   restore it later).  Note that the pointer to a user defined error
Packit 67cb25
   handler function is stored in a static variable, so there can be only
Packit 67cb25
   one error handler per program.  This function should be not be used in
Packit 67cb25
   multi-threaded programs except to set up a program-wide error handler
Packit 67cb25
   from a master thread.  The following example shows how to set and
Packit 67cb25
   restore a new error handler::
Packit 67cb25
Packit 67cb25
     /* save original handler, install new handler */
Packit 67cb25
     old_handler = gsl_set_error_handler (&my_handler); 
Packit 67cb25
Packit 67cb25
     /* code uses new handler */
Packit 67cb25
     .....     
Packit 67cb25
Packit 67cb25
     /* restore original handler */
Packit 67cb25
     gsl_set_error_handler (old_handler); 
Packit 67cb25
Packit 67cb25
   To use the default behavior (:func:`abort` on error) set the error
Packit 67cb25
   handler to :code:`NULL`::
Packit 67cb25
Packit 67cb25
     old_handler = gsl_set_error_handler (NULL); 
Packit 67cb25
Packit 67cb25
.. function:: gsl_error_handler_t * gsl_set_error_handler_off ()
Packit 67cb25
Packit 67cb25
   This function turns off the error handler by defining an error handler
Packit 67cb25
   which does nothing. This will cause the program to continue after any
Packit 67cb25
   error, so the return values from any library routines must be checked.
Packit 67cb25
   This is the recommended behavior for production programs.  The previous
Packit 67cb25
   handler is returned (so that you can restore it later).
Packit 67cb25
Packit 67cb25
The error behavior can be changed for specific applications by
Packit 67cb25
recompiling the library with a customized definition of the
Packit 67cb25
:code:`GSL_ERROR` macro in the file :file:`gsl_errno.h`.
Packit 67cb25
Packit 67cb25
.. index:: error handling macros
Packit 67cb25
Packit 67cb25
Using GSL error reporting in your own functions
Packit 67cb25
===============================================
Packit 67cb25
Packit 67cb25
If you are writing numerical functions in a program which also uses GSL
Packit 67cb25
code you may find it convenient to adopt the same error reporting
Packit 67cb25
conventions as in the library.
Packit 67cb25
Packit 67cb25
To report an error you need to call the function :func:`gsl_error` with a
Packit 67cb25
string describing the error and then return an appropriate error code
Packit 67cb25
from :file:`gsl_errno.h`, or a special value, such as :code:`NaN`.  For
Packit 67cb25
convenience the file :file:`gsl_errno.h` defines two macros which carry
Packit 67cb25
out these steps:
Packit 67cb25
Packit 67cb25
.. macro:: GSL_ERROR (reason, gsl_errno)
Packit 67cb25
Packit 67cb25
   This macro reports an error using the GSL conventions and returns a
Packit 67cb25
   status value of :code:`gsl_errno`.  It expands to the following code fragment::
Packit 67cb25
Packit 67cb25
     gsl_error (reason, __FILE__, __LINE__, gsl_errno);
Packit 67cb25
     return gsl_errno;
Packit 67cb25
Packit 67cb25
   The macro definition in :file:`gsl_errno.h` actually wraps the code
Packit 67cb25
   in a :code:`do { ... } while (0)` block to prevent possible
Packit 67cb25
   parsing problems.
Packit 67cb25
Packit 67cb25
Here is an example of how the macro could be used to report that a
Packit 67cb25
routine did not achieve a requested tolerance.  To report the error the
Packit 67cb25
routine needs to return the error code :code:`GSL_ETOL`::
Packit 67cb25
Packit 67cb25
    if (residual > tolerance) 
Packit 67cb25
      {
Packit 67cb25
        GSL_ERROR("residual exceeds tolerance", GSL_ETOL);
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
.. macro:: GSL_ERROR_VAL (reason, gsl_errno, value)
Packit 67cb25
Packit 67cb25
   This macro is the same as :code:`GSL_ERROR` but returns a user-defined
Packit 67cb25
   value of :data:`value` instead of an error code.  It can be used for
Packit 67cb25
   mathematical functions that return a floating point value.
Packit 67cb25
Packit 67cb25
The following example shows how to return a :code:`NaN` at a mathematical
Packit 67cb25
singularity using the :code:`GSL_ERROR_VAL` macro::
Packit 67cb25
Packit 67cb25
    if (x == 0) 
Packit 67cb25
      {
Packit 67cb25
        GSL_ERROR_VAL("argument lies on singularity", GSL_ERANGE, GSL_NAN);
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
Packit 67cb25
Examples
Packit 67cb25
========
Packit 67cb25
Packit 67cb25
Here is an example of some code which checks the return value of a
Packit 67cb25
function where an error might be reported::
Packit 67cb25
Packit 67cb25
    #include <stdio.h>
Packit 67cb25
    #include <gsl/gsl_errno.h>
Packit 67cb25
    #include <gsl/gsl_fft_complex.h>
Packit 67cb25
Packit 67cb25
    ...
Packit 67cb25
      int status;
Packit 67cb25
      size_t n = 37;
Packit 67cb25
Packit 67cb25
      gsl_set_error_handler_off();
Packit 67cb25
Packit 67cb25
      status = gsl_fft_complex_radix2_forward (data, stride, n);
Packit 67cb25
Packit 67cb25
      if (status) {
Packit 67cb25
        if (status == GSL_EINVAL) {
Packit 67cb25
           fprintf (stderr, "invalid argument, n=%d\n", n);
Packit 67cb25
        } else {
Packit 67cb25
           fprintf (stderr, "failed, gsl_errno=%d\n", status);
Packit 67cb25
        }
Packit 67cb25
        exit (-1);
Packit 67cb25
      }
Packit 67cb25
    ...
Packit 67cb25
Packit 67cb25
The function :func:`gsl_fft_complex_radix2_forward` only accepts integer lengths
Packit 67cb25
which are a power of two.  If the variable :code:`n` is not a power of
Packit 67cb25
two then the call to the library function will return :code:`GSL_EINVAL`,
Packit 67cb25
indicating that the length argument is invalid.  The function call to
Packit 67cb25
:func:`gsl_set_error_handler_off` stops the default error handler from
Packit 67cb25
aborting the program.  The :code:`else` clause catches any other possible
Packit 67cb25
errors.
Packit 67cb25