Xref: utzoo comp.lang.c:34536 comp.unix.programmer:633 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!think.com!mintaka!bloom-picayune.mit.edu!news From: scs@adam.mit.edu (Steve Summit) Newsgroups: comp.lang.c,comp.unix.programmer Subject: Error handling Keywords: errno Message-ID: <1990Dec6.053854.10365@athena.mit.edu> Date: 6 Dec 90 05:38:54 GMT References: <14617@smoke.brl.mil> Sender: news@athena.mit.edu (News system) Reply-To: scs@adam.mit.edu (Steve Summit) Organization: Thermal Technologies, Inc. Lines: 89 While I'm up on an error handling soapbox, I'd like to discuss what else to do with errno values other than call perror to interpret and print them. (This relates to a long discussion which raged on comp.unix. er, "internals" a while ago. I'm crossposting to comp.unix.programmer because this pertains mostly to Unix/Posix programming.) In article <14617@smoke.brl.mil>, Doug Gwyn pointed out that (in Posix), >The allowable values of errno ( >macros) are specified for each function. While this is useful information, and helps you figure out how each function might fail, it is often a bad idea to build knowledge of specific errno values into a program. To be sure, some errno values may be interesting, and a program may well wish to handle them specially, but (as evidenced by recent discussion) a lot of people seem to want to believe that the documented vales are guaranteed to be the only only ones that the function will ever "return." This is a dangerous and unnecessary assumption. It leads to code that ignores error returns because the author inspected the list of possible errno's and decided that the program could handle all of them, or that all of them "couldn't happen" (or that it couldn't handle any of them, and "don't check for error conditions you can't handle"). All of these rationalizations are poor. Don't use (void)syscall(...); or if(syscall(...) < 0) { switch(errno) { case ENOENT: /* ...build one... */ break; case EINTR: /* ...retry... */ break; } } Most of the time, use something like if(syscall(...) < 0) { perror("syscall failed"); return ERROR; } (but see my previous article for other useful information which should be included in the error message, and how to do so conveniently.) If there are a few errno values which you know how to "correct" (i.e. handle in some special way), use code like the switch statement above, but include a default case: default: perror("syscall failed"); return ERROR; If the system call "can't fail," or if your program "can't handle it" (i.e. somehow has to keep processing, even though the system call failed), or if a failure truly wouldn't matter (e.g. close fails on a file open for reading), at least use something like if(syscall(...) < 0) { perror("warning: syscall failed"); fprintf(stderr, "(continuing anyway; hope things are okay)\n"); } This lets the user know that something might be amiss. No matter what the documentation says today, errno values are the sort of thing that change all the time (or are implemented slightly incorrectly by a system implementer who didn't read the fine print), and it is useful to add new ones as systems expand or are otherwise improved, so it makes sense for a program that might be around for a while to anticipate the occurrence of errno's it hasn't heard of yet. Steve Summit scs@adam.mit.edu Brought to you by Super Global Mega Corp .com