(com_err.info)Coding Conventions


Next: Building and Installation Prev: Run-time support routines Up: Top
Enter node , (file) or (file)node

6 Coding Conventions
********************

The following conventions are just some general stylistic conventions to
follow when writing robust libraries and programs.  Conventions similar
to this are generally followed inside the UNIX kernel and most routines
in the Multics operating system.  In general, a routine either succeeds
(returning a zero error code, and doing some side effects in the
process), or it fails, doing minimal side effects; in any event, any
invariant which the library assumes must be maintained.

   In general, it is not in the domain of non user-interface library
routines to write error messages to the user's terminal, or halt the
process.  Such forms of "error handling" should be reserved for failures
of internal invariants and consistency checks only, as it provides the
user of the library no way to clean up for himself in the event of total
failure.

   Library routines which can fail should be set up to return an error
code.  This should usually be done as the return value of the function;
if this is not acceptable, the routine should return a "null" value, and
put the error code into a parameter passed by reference.

   Routines which use the first style of interface can be used from
user-interface levels of a program as follows:

     {
         if ((code = initialize_world(getuid(), random())) != 0) {
             com_err("demo", code,
                     "when trying to initialize world");
             exit(1);
         }
         if ((database = open_database("my_secrets", &code))==NULL) {
             com_err("demo", code,
                     "while opening my_secrets");
             exit(1);
         }
     }

   A caller which fails to check the return status is in error.  It is
possible to look for code which ignores error returns by using lint;
look for error messages of the form "foobar returns value which is
sometimes ignored" or "foobar returns value which is always ignored."

   Since libraries may be built out of other libraries, it is often
necessary for the success of one routine to depend on another.  When a
lower level routine returns an error code, the middle level routine has
a few possible options.  It can simply return the error code to its
caller after doing some form of cleanup, it can substitute one of its
own, or it can take corrective action of its own and continue normally.
For instance, a library routine which makes a "connect" system call to
make a network connection may reflect the system error code
'ECONNREFUSED' (Connection refused) to its caller, or it may return a
"server not available, try again later," or it may try a different
server.

   Cleanup which is typically necessary may include, but not be limited
to, freeing allocated memory which will not be needed any more,
unlocking concurrency locks, dropping reference counts, closing file
descriptors, or otherwise undoing anything which the procedure did up to
this point.  When there are a lot of things which can go wrong, it is
generally good to write one block of error-handling code which is
branched to, using a goto, in the event of failure.  A common source of
errors in UNIX programs is failing to close file descriptors on error
returns; this leaves a number of "zombied" file descriptors open, which
eventually causes the process to run out of file descriptors and fall
over.

     {
         FILE *f1=NULL, *f2=NULL, *f3=NULL;
         int status = 0;

         if ( (f1 = fopen(FILE1, "r")) == NULL) {
             status = errno;
             goto error;
         }

         /*
          * Crunch for a while
          */

         if ( (f2 = fopen(FILE2, "w")) == NULL) {
             status = errno;
             goto error;
         }

         if ( (f3 = fopen(FILE3, "a+")) == NULL) {
             status = errno;
                 goto error;
         }

         /*
          * Do more processing.
          */
         fclose(f1);
         fclose(f2);
         fclose(f3);
         return 0;

     error:
         if (f1) fclose(f1);
         if (f2) fclose(f2);
         if (f3) fclose(f3);
         return status;
     }


automatically generated by info2www version 1.2.2.9