HowTo: Error Handling

written by jahlborn@parc.xerox.com 
(please direct questions and comments here)


Outline:

  1. General function setup

  2. "Main" function setup

  3. Handling errors

  4. Error printers

  5. Error Codes

  6. Assertions


Specifics:

1. General function setup

ErrCode foo(...args...) 
{ 
  DGP_PROLOGUE("foo()", <perr_state>);  <-set the error state variable for the function
  ...body...
  NORMAL_RETURN;  <- return with no errors
  // possibly with this part, if cleanup is needed 
ERR_CLEANUP:      <- optional block of code to jump to in case of errors
  ...cleanup code...
  ERR_RETURN;     <- return an error
}

Notes:

Example: 

(two functions: foo() which calls my_funct(), both return errors):

#include "dgp_err_control.h"
ErrCode my_funct(..., DgpState *dgp_state) 
{
  DGP_PROLOGUE("my_funct()", dgp_pErrState);  <-set the error state to whatever is in the dgp_state
  void *array = NULL;
  ... 
  DGP_CHECK_ALLOC_CLEANUP(array = dgp_Malloc(this_size)); <-error checked memory allocation (using dgp allocators)
  ...
  NORMAL_RETURN;  <-return if nothing fails
ERR_CLEANUP:      <-jump here on errors
  ...
  if(array != NULL) dgp_Free(array);  <-free the array we allocated (using dgp allocators)
  ERR_RETURN;     <-return an error
}
ErrCode foo(..., DgpState *dgp_state) 
{
  DGP_PROLOGUE("foo", dgp_pErrState);  <-set the error state to whatever is in the dgp_state
  ... 
  DGP_ERR_PASS(my_funct(..., dgp_state)); <-error checked function call
  ...
  NORMAL_RETURN;  <-normal return if no errors
}

2. "Main" function setup

int main(int argc, char **argv) 
{ 
  DGP_MAIN_PROLOGUE("main()", <perr_cookie>, <perr_printer>);  <-set error printer and cookie
  ...body...
  MAIN_NORMAL_RETURN;  <-return EXIT_SUCCESS
// possibly with this part, if cleanup is needed 
ERR_CLEANUP:           <-jump here on errors
  ...cleanup code...
  MAIN_ERR_RETURN;     <-return EXIT_FAILURE
}

Notes: 

Example:

#include "dgp_err_control.h" 
#include "dgp_err_printers.h"
int main(int argc, char **argv) 
{ 
  DGP_MAIN_PROLOGUE("main()", stderr, Dgp_FileErrPrinter);  <-use stderr for error output now.
  DgpState *dgp_state = NULL;
  ...
  DGP_ERR_PASS_CLEANUP(Dgp_InitDgpState(&dgp_state, ..., my_err_cookie, my_err_printer,...));
                                     ^-error checked function call to create a digipaper state.
  DGP_SET_ERR_STATE(dgp_pErrState);  <-change current error output to my_err_cookie and my_err_printer
  ...
  ...main body...
  ...
  Dgp_CleanupDgpState(&dgp_state);  <-cleanup dgp state
  MAIN_NORMAL_RETURN;  <-return EXIT_SUCCESS
// possibly with this part, if cleanup is needed 
ERR_CLEANUP:           <-jump here on errors
  ...
  Dgp_CleanupDgpState(&dgp_state);  <-cleanup dgp state in case of errors
  ...
  MAIN_ERR_RETURN;     <-return EXIT_FAILURE
}

Notes: 

3. Handling errors

There are many macros to handle errors in dgp_err_control.h, dgp_xif_err_control.h, dgp_sys_err_control.h, and dgp_w32_err_control.h. The first part will be the common, general use macros (dgp_err_control.h), and the second part will give more specifics on the other files.

Other macros: 

There are other macros to do more complicated or fine grained things, you'll have to check them out for yourself. You can do pretty much whatever you need to if you find the right macros. (ask jahlborn@parc.xerox.com for help if you need it). HOWEVER, please try to use the defined macros, not the actual variables themselves. If you use the variables themselves and changes are made, your code goes kaput... bad. If you use the macros, chances are, the functionality will remain the same, and your code will continue to build... mmmmm, good.

Specialized error handler macros:

4. Error printers

liberr has some default error handlers built into it, or you can write your own. The default handlers are (you must include dgp_err_printers.h):

Notes for defining your own error handler:

5. Error Codes

The error codes we use are mainly from ipcore (ipwerrs.pub, ipserrs.pub) with some of our own defined in dgp_errs.h.

New Error Codes:

...
#define cErrFoo cDgpGen + 10 /* My foo error for when things go foo!*/  <-your new error code!
...
...
#define NUM_DGP_ERRORS 11           <-updated from its former value of 10
...
char *DGP_ERRORS[NUM_DGP_ERRORS] = {
...
"The old last error string", // cErrPrev cDgpGen + 9   <-former last error string (add comma)
"My new error string foo" // cErrFoo cDgpGen + 10      <-new last error string
...
}

6. Assertions

Assertions in digipaper work much like normal assertions, but with a few small differences:

 


$Header: /project/icons/cvsroot/digipaper/doc/Error\040Handling.htm,v 1.3 2000/04/28 21:39:49 jahlborn Exp $