Linux for Programmers and Users

[Page 434 (continued)]

12.2. Error Handling: perror ()

Most system calls are capable of failing in some way. For example, the open () system call will fail if you try to open a nonexistent file for reading. By convention, all system calls return -1 if an error occurs. However, this doesn't tell you much about why the error occurred; the open () system call can fail for one of several different reasons. If you want to deal with system call errors in a systematic way, you must know about two things:

  • errno, a global variable that holds the numeric code of the last system call error

  • perror (), a subroutine that describes system call errors

Every process contains a global variable called errno, which is originally set to zero when the process is created. When a system call error occurs, errno is set to the numeric code associated with the cause of the error. For example, if you try to open a file that doesn't exist for reading, errno is set to 2. These predefined error codes are defined in a C program by including the file "/usr/include/errno.h" (which itself includes other platform-specific files). The names of the error codes are also listed in the errno man page. Here's a snippet of the file "/usr/include/asm/errno.h" on my system, where the error constants are defined:

#define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */

The value of errno only has a meaning following an unsuccessful system call which overwrites the current value of errno. A successful system call is not guaranteed to leave errno unmodified (as it is in some versions of UNIX). To access errno from your program, include <errno.h>. The perror () subroutine converts the current value of errno into a text description (Figure 12-4).


[Page 435]

Figure 12-4. Description of the perror () system call.

Library Function: void perror (char* str)

perror () displays the string str, followed by a colon, followed by a description of the last system call error. If there is no error to report, it displays the string "Error 0." Actually, perror () isn't a system callit's a standard C library function.

Your program should check system calls for a return value of -1 and then deal with the error. One of the first things to do in these situations, especially during debugging, is to call perror () for a description of the error.

In the following example, I forced a couple of system call errors to demonstrate perror (), and then demonstrated that errno did not retain the last system call error code after a subsequent successful call was made. Don't worry about how open () works; I'll describe it later in this chapter.

$ cat showErrno.c #include <stdio.h> #include <fcntl.h> #include <errno.h> main () { int fd; /* Open a nonexistent file to cause an error */ fd = open ("nonexist.txt", O_RDONLY); if (fd == -1) /* fd == -1 =, an error occurred */ { printf ("errno = %d\n", errno); perror ("main"); } fd = open ("/", O_WRONLY); /* Force a different error */ if (fd == -1) { printf ("errno = %d\n", errno); perror ("main"); } /* Execute a successful system call */ fd = open ("nonexist.txt", O_RDONLY | O_CREAT, 0644); printf ("errno = %d\n", errno); /* Display after successful call */ perror ("main"); errno = 0; /* Manually reset error variable */ perror ("main"); }


[Page 436]

Here's the output from the program shown above:

$ ./showErrno ...run the program. errno = 2 main: No such file or directory errno = 21 main: Is a directory errno = 29 ...even after a successful call main: Illegal seek main: Success ...after we reset manually. $ _

Категории