Error Handling

Netpbm Programming Library Errors

As part of Netpbm's mission to make writing graphics programs quick and easy, Netpbm recognizes that no programmer likes to deal with error conditions. Therefore, very few Netpbm programming library functions return error information. There are no return codes to check. If for some reason a function can't do what was asked of it, it doesn't return at all.

Netpbm's response to encountering an error is called "throwing an error."

The typical way a Netpbm function throws an error (for example, when you attempt to open a non-existent file with pm_openr()) is that the function writes an error message the the Standard Error file and then causes the program to terminate with an exit() system call. The function doesn't do any explicit cleanup, because everything a library function sets up gets cleaned up by normal process termination.

In many cases, that simply isn't acceptable. If you're calling Netpbm functions from inside a server program, you'd want the program to recognize that the immediate task failed, but keep running to do other work.

So as an alternative, you can have the library functions throw an error by executing a longjmp instead. A longjmp is a classic Unix exception handling concept. See the documentation of the standard C library setjmp() and longjmp() functions.

In short, you identify a point in your programs for execution to hyperjump to from whatever depths of whatever functions it may be in at the time it detects an exception. That hyperjump is called a longjmp. The longjmp unwinds the stack and puts the program in the same state as if the subroutines had returned all the way up to the function that contains the jump point. A longjmp does not in itself undo things like memory allocations. But when you have a Netpbm function do a longjmp, it also cleans up everything it started.

To select this form of throwing an error, use the pm_setjmpbuf() function. This alternative is not available before Netpbm 10.27 (March 2005).

pm_setjmpbuf()

pm_setjmpbuf() sets up the process so that when future calls to the Netpbm programming library throw an error, they execute a longjmp instead of causing the process to exit as they would by default.

This is not analogous to setjmp(). You do a setjmp() first, then tell the Netpbm programming library with pm_setjmpbuf() to use the result.

Example:


  #include <setjmp.h>
  #include <pam.h>

  jmp_buf jmpbuf;
  int rc;

  rc = setjmp(jmpbuf);
  if (rc == 0) {
    struct pam pam;
    pm_setjmpbuf(&jmpbuf);
    
    pnm_readpam(stdin, &pam, PAM_STRUCT_SIZE(tuple_type));

    printf("pnm_readpam() succeeded!\n");

  } else {
    printf("pnm_readpam() failed.  You should have seen "
           "messages to Standard Error telling you why.\n");
  }

This example should look really strange to you if you haven't read the documentation of setjmp(). Remember that there is a hyperjump such that code that the program is executing the pnm_readpam() and then suddenly is returning a second time from the setjmp()!

Even pm_error() works this way -- if you set up a longjmp with pm_setjmpbuf() and then call pm_error(), pm_error() will, after issuing your error message, execute the longjmp.

pm_setjmpbuf() was new in Netpbm 10.27 (March 2005). Before that, Netpbm programming library functions always throw an error by exiting the program.

User Detected Errors

The Netpbm programming library provides a function for you to throw an error explicitly: pm_error(). pm_error() does nothing but throw an error, and does so the same way any Netpbm library function you call would. pm_error() is more convenient than most standard C facilities for handling errors.

pm_error()

Overview

void pm_error( char * fmt, ... );

Example


if (argc-1 < 3)
    pm_error("You must specify at least 3 arguments.  "
             "You specified" only %d", argc-1);

pm_error() is a printf() style routine that simply throws an error. The error message it issues as part of that is the message described by the arguments.

Note that the arguments specify the message text, not any formatting of it. Formatting is handled by pm_error(). So don't put any newlines or tabs in it.

Error Handling In Netpbm Programs

Most Netpbm programs respond to encountering an error by issuing a message describing the error to the Standard Error file and then exiting with exit status 1.

Netpbm programs generally do not follow the Unix convention of very terse error messages. Conventional Unix programs produce error messages as if they had to pay by the word. Netpbm programs tend to give a complete description of the problem in human-parseable English. These messages are often many terminal lines long.