diff options
Diffstat (limited to 'error.html')
-rw-r--r-- | error.html | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/error.html b/error.html new file mode 100644 index 00000000..68383b4f --- /dev/null +++ b/error.html @@ -0,0 +1,250 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> +<TITLE>Netpbm User Manual</TITLE> +</HEAD> +<BODY> +<H1>Error Handling</H1> + +<h2>Netpbm Programming Library Errors</h2> + +<p>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. + +<p>Netpbm's response to encountering an error is called "throwing +an error." + +<p>The typical way a Netpbm function throws an error (for example, +when you attempt to open a non-existent file with <b>pm_openr()</b>) +is that the function writes an error message to 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. + +<p>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. + +<p>So as an alternative, you can replace that program exit with a +longjmp instead. A longjmp is a classic Unix exception handling +concept. See the documentation of the standard C library +<b>setjmp()</b> and <b>longjmp()</b> functions. + +<p>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. + +<p>To select this form of throwing an error, use the +<b>pm_setjmpbuf()</b> function. This alternative is not available +before Netpbm 10.27 (March 2005). + +<p>Issuing of the error message is a separate thing. Regardless +of whether a library routine exits the program or executes a longjmp, +it issues an error message first. + +<p>You can customize the error message behavior too. By default, a +Netpbm function issues an error message by writing it to the Standard +Error file, formatted into a single line with the program name prefixed. +But you can register your own error message function to run instead with +<b>pm_setErrorMsgFn()</b>. + + +<h3 id="pm_setjmpbuf">pm_setjmpbuf()</h3> + +<p>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. + +<p>This is <em>not</em> analogous to <b>setjmp()</b>. You do a +setjmp() first, then tell the Netpbm programming library with +<b>pm_setjmpbuf()</b> to use the result. + +<p>Example: + +<pre> +<code> + #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"); + } +</code> +</pre> + +<P>This example should look really strange to you if you haven't read +the documentation of <b>setjmp()</b>. Remember that there is a +hyperjump such that the program is executing the <b>pnm_readpam()</b> +and then suddenly is returning a second time from the setjmp()! + +<p>Even <b>pm_error()</b> works this way -- if you set up a longjmp with +<b>pm_setjmpbuf()</b> and then call <b>pm_error()</b>, <b>pm_error()</b> +will, after issuing your error message, execute the longjmp. + + +<p><b>pm_setjmpbuf()</b> was new in Netpbm 10.27 (March 2005). Before +that, Netpbm programming library functions always throw an error by +exiting the program. + + +<h2>User Detected Errors</h2> + +<p>The Netpbm programming library provides a function for you to throw +an error explicitly: <b>pm_error()</b>. <b>pm_error()</b> does +nothing but throw an error, and does so the same way any Netpbm +library function you call would. <b>pm_error()</b> is more convenient +than most standard C facilities for handling errors. + +<p>If you don't want to throw an error, but just want to issue an +error message, use <b>pm_errormsg()</b>. It issues the message in the +same way as <b>pm_error()</b> but returns normally instead of longjmping +or exiting the program. + +<p>Note that <b>libnetpbm</b> distinguishes between an error message +and an informational message (use <b>pm_errormsg()</b> for the former; +<b>pm_message()</b> for the latter). The only practical difference is +which user message function it calls. So if you don't register any +user message function, you won't see any difference, but a program is +still more maintainable and easier to read when you use the +appropriate one of these. + + +<h3 id="pm_error">pm_error()</h3> + +<h4>Overview</h4> + +<p> +<B>void pm_error(</b> +<b>char *</B> <I>fmt</I><B>,</B> +<B>... );</B> + +<h4>Example</h4> + +<pre> +<code> +if (argc-1 < 3) + pm_error("You must specify at least 3 arguments. " + "You specified" only %d", argc-1); +</code> +</pre> + +<P><B>pm_error()</B> is a <B>printf()</B> style routine that +simply throws an error. It issues an error message exactly like +<b>pm_errormsg()</b> would in the process. + + +<h3 id="pm_errormsg">pm_errormsg()</h3> + +<h4>Overview</h4> + +<p> +<B>void pm_errormsg(</b> +<b>char *</B> <I>fmt</I><B>,</B> +<B>... );</B> + +<h4>Example</h4> + +<pre> +<code> +if (rc = -1) + pm_errormsg("Could not open file. errno=%d", errno); + return -1; +</code> +</pre> + +<P><B>pm_errormsg()</B> is a <B>printf()</B> style routine that +issues an error message. By default, it writes the message to Standard +Error, but you can register a user error message routine to be called +instead, and that might do something such as write the message into a +log file. See <a href="#pm_setusererrormsgfn"><b>pm_setusererrormsgfn</b></a>. + +<p>There is very little advantage to using this over traditional C +services, but it issues a message in the same way as <b>libnetpbm</b> +library functions do, so the common handling might be valuable. + +<p>Note that the arguments specify the message text, not any formatting +of it. Formatting is handled by <b>pm_errormsg()</b>. So don't put any +newlines or tabs in it. + + +<h3 id="pm_setusererrormsgfn">pm_setusererrormsgfn()</h3> + +<h4>Overview</h4> + +<p> +<B>void pm_setusererrormsgfn(pm_usererrormsgfn *</B> <I>function</I><B>);</b> + +<h4>Example</h4> + +<pre> +<code> + static pm_usererrormsgfn logfilewrite; + + static void + logfilewrite(const char * const msg) { + fprintf(myerrorlog, "Netpbm error: %s", msg); + } + + pm_setusererrormsgfn(&logfilewrite); + + pm_errormsg("Message for the error log"); +</code> +</pre> + +<P><B>pm_setusererrormsg()</B> registers a handler for error messages, +called a user error message routine. Any library function that wants +to issue an error message in the future will call that function with +the message as an argument. + +<p>The argument the user error message routine gets is English text +designed for human reading. It is just the text of the message; there +is no attempt at formatting in it (so you won't see any newline or tab +characters). + +<p>You can remove the user error message routine, so that the library +issues future error messages in its default way (write to Standard Error) +by specifying a null pointer for <i>function</i>. + +<p>The user error message routine does not handle informational messages. +It handles only error messages. See <a href="libpm.html#message"> +<b>pm_setusermessagefn()</b></a>. + + +<h2>Error Handling In Netpbm Programs</h2> + +<p>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. + +<p>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. + +</body> +</html> |