aeb@mcvax.UUCP (Andries Brouwer) (06/27/85)
The following short C program
main(){
extern int errno;
errno = 0;
putchar('\n');
if(errno > 0)
perror("perror");
}
gives unexpected results.
E.g.
a.out | ...
gives the error message "Operation not supported on socket".
The reason is that putchar calls putc calls _flsbuf calls isatty
and isatty contains the code
if(ioctl(f,TIOCGETP,&ttyb)<0)
return(0);
Probably it should do errno = 0 before the return(0).
We noticed this bug because the new pic and eqn started to give
strange error messages.
geoff@desint.UUCP (Geoff Kuenning) (07/06/85)
In article <726@mcvax.UUCP> aeb@mcvax.UUCP (Andries Brouwer) writes: >The following short C program > >main(){ > extern int errno; > > errno = 0; > putchar('\n'); > if(errno > 0) > perror("perror"); >} > >gives unexpected results. >E.g. > a.out | ... >gives the error message "Operation not supported on socket". >The reason is...[that putchar can leave errno nonzero even in nonerror cases] Um, I think errno is specified to be valid only if putchar returns the constant EOF. Thus, the code should be: if (putchar ('\n') == EOF) perror ("putchar"); Incidentally, this brings up a bug in putc/putchar. On both BSD and VMS, the following code will print a message, even though the putchar succeeds: if (putchar ('\377') == EOF) fprintf (stderr, "you have the bug!\n"); The problem is that, in <stdio.h>, the putc macro neglects to cast its argument to an *unsigned* character, so it gets sign-extended on return to -1. The fix is easy; I won't post it because (a) I don't have BSD at my fingertips at the moment and (b) it's probably a licensing violation anyway. -- Geoff Kuenning ...!ihnp4!trwrb!desint!geoff
jww@sdcsvax.UUCP (Joel West) (07/10/85)
> The following short C program > > main(){ > extern int errno; > > errno = 0; > putchar('\n'); > if(errno > 0) > perror("perror"); > } > > gives unexpected results. > The reason is that putchar calls putc calls _flsbuf calls isatty > and isatty contains the code > if(ioctl(f,TIOCGETP,&ttyb)<0) > return(0); (which sets errno=25: not a typewriter unless stdout is /dev/tty) I was going to post this one myself. I found it on BSD 4.2, System V/2.0 and UTX-32 (a Gould BSD + V port). It really screwed me up bad. The other 'gotcha' (same systems) is mktemp, which attempts to build a unique file name. errno is always 2 (file not found) after successfully calling mktemp on these 3 systems.
aeb@mcvax.UUCP (Andries Brouwer) (07/10/85)
In article <112@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes: >Um, I think errno is specified to be valid only if putchar returns the >constant EOF. Thus, the code should be: > > if (putchar ('\n') == EOF) > perror ("putchar"); > Unfortunately, this is not true. errno is set by system calls, but not by the stdio library routines. Thus, when a stdio library routine fails it may be that errno contains useful information (in case the failure was due to a system call error return), but it may also be that errno contains garbage (in case the library routine detected the error itself). Thus, fopen can fail when all _iob entries are taken; putc can fail when writing to a stream that has not been opened for writing, etc. This means that you cannot reliably use the stdio routines when you want to do error recovery. Example: #include <stdio.h> main(){ putchar('\n'); /* sets errno via isatty() */ fclose(stdout); /* make next putchar fail */ if(putchar('\n') == EOF) perror("putchar"); /* produce garbage */ } Again, the call a.out > /dev/null will produce putchar: no such device, and a.out | ... produces putchar: operation not supported on socket.
mjs@eagle.UUCP (M.J.Shannon) (07/10/85)
> In article <112@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes: > >Um, I think errno is specified to be valid only if putchar returns the > >constant EOF. Thus, the code should be: > > > > if (putchar ('\n') == EOF) > > perror ("putchar"); > > > > Unfortunately, this is not true. > errno is set by system calls, but not by the stdio library routines. > Thus, when a stdio library routine fails it may be that errno > contains useful information (in case the failure was due to a > system call error return), but it may also be that errno contains > garbage (in case the library routine detected the error itself). > Thus, fopen can fail when all _iob entries are taken; putc can fail > when writing to a stream that has not been opened for writing, etc. > > This means that you cannot reliably use the stdio routines when you want > to do error recovery. > > Example: > #include <stdio.h> > main(){ > putchar('\n'); /* sets errno via isatty() */ > fclose(stdout); /* make next putchar fail */ > if(putchar('\n') == EOF) > perror("putchar"); /* produce garbage */ > } > Again, the call a.out > /dev/null will produce putchar: no such device, > and a.out | ... produces putchar: operation not supported on socket. How about using the routine which is part of stdio to determine the presence of errors? I beileve it's called ferror(iop). The only problem is that the programmer must determine what the error was by context..... -- Marty Shannon UUCP: ihnp4!eagle!mjs Phone: +1 201 522 6063
smb@ulysses.UUCP (Steven Bellovin) (07/11/85)
> > The following short C program > > > > main(){ > > extern int errno; > > > > errno = 0; > > putchar('\n'); > > if(errno > 0) > > perror("perror"); > > } > > > > gives unexpected results. > > The reason is that putchar calls putc calls _flsbuf calls isatty > > and isatty contains the code > > if(ioctl(f,TIOCGETP,&ttyb)<0) > > return(0); > > (which sets errno=25: not a typewriter unless stdout is /dev/tty) > > I was going to post this one myself. I found it on BSD 4.2, > System V/2.0 and UTX-32 (a Gould BSD + V port). It really > screwed me up bad. > > The other 'gotcha' (same systems) is mktemp, which attempts > to build a unique file name. errno is always 2 (file not > found) after successfully calling mktemp on these 3 systems. The manual warns you that errno is not cleared on successful calls, so you're not allowed to check it unless you've gotten an error return -- say, a -1 from a system call. With stdio, use ferror() to detect problems.
dbaker@cuuxb.UUCP (Darryl Baker) (07/18/85)
In article <965@sdcsvax.UUCP> jww@sdcsvax.UUCP (Joel West) writes: >> The following short C program >> >> main(){ >> extern int errno; >> >> errno = 0; >> putchar('\n'); >> if(errno > 0) >> perror("perror"); >> } >> >> gives unexpected results. .... Stuff deleted to save space and keep people interested. .... >The other 'gotcha' (same systems) is mktemp, which attempts >to build a unique file name. errno is always 2 (file not >found) after successfully calling mktemp on these 3 systems. Now I am not going to go into a long explanation of poor coding, but aren't you supposed to check return values for errors. Lots of section 3 routines call things from section 2 that set errno. Also isn't also true that the intro to section 2 states that errno is not cleared on successful calls.
scw@ucla-cs.UUCP (07/19/85)
In article <243@cuuxb.UUCP> dbaker@cuuxb.UUCP (Darryl Baker) writes: >In article <965@sdcsvax.UUCP> jww@sdcsvax.UUCP (Joel West) writes: >>> The following short C program >>> >>> main(){ >>> extern int errno; >>> >>> errno = 0; >>> putchar('\n'); >>> if(errno > 0) >>> perror("perror"); >>> } >>> >>> gives unexpected results. > .... > Stuff deleted to save space > and keep people interested. > .... >>The other 'gotcha' (same systems) is mktemp, which attempts >>to build a unique file name. errno is always 2 (file not >>found) after successfully calling mktemp on these 3 systems. > >Now I am not going to go into a long explanation of poor coding, but aren't >you supposed to check return values for errors. Lots of section 3 routines >call things from section 2 that set errno. Also isn't also true that the >intro to section 2 states that errno is not cleared on successful calls. The expected value of errno after a mktemp() is 2. mktemp() keeps playing with stat() (I think) and munging the name that it's trying until it fails to find the file, hence this name is unique. The problem is that mktemp() really should clear errno after the last attempt, or that errno == 2 should be a feature (in the BUGS section of mktemp(III)). In fact (on second consideration) you should assume that an errno != 2 means that mktemp() has failed (you didn't allow enough XXXXXX's to generate a unique name). As an aside, has anyone noticed that DEC and [name deleted] have removed the BUGS entries from the man pages? I guess that they're afraid that non UN*X people will think that BUGS means buggy programs, not unavoidable/historical artifacts. Gould however has done the correct thing, They renamed it 'Special Considerations' (rather well named neh?).
jww@sdcsvax.UUCP (Joel West) (07/21/85)
> In article <243@cuuxb.UUCP> dbaker@cuuxb.UUCP (Darryl Baker) writes: > > The expected value of errno after a mktemp() is 2. > ... The problem is that mktemp() > really should clear errno after the last attempt, or that errno == 2 should > be a feature (in the BUGS section of mktemp(III)). For those keepers of the true faith who savaged my coding practices, this is exactly my point. I designed a large software system around the assumption that errno was always valid and not set as a side-effect. It took me 6 months (admittedly, I wasn't looking hard) to figure out why I was always getting "not a typewriter" (because my open routine was setting a struct bit to indicate tty/non-tty for every file). My reason for posting this was to call attention to an error in the documentation. All the manuals I've seen are in error, because this is a known, established, important "SPECIAL CONSIDERATION". > As an aside, has anyone noticed that DEC and [name deleted] have removed the > BUGS entries from the man pages? I guess that they're afraid that non UN*X > people will think that BUGS means buggy programs, not unavoidable/historical > artifacts. [Name deleted] must refer to my AT&T System V/2.0 manuals. > Gould however has done the correct thing, They renamed it 'Special > Considerations' (rather well named neh?). The Gould folks tell me they can't call it "Bugs" (Everyone has enough problems with those anyway) for marketting reasons. But at least they left it in. I don't care what it's called, as long as it's there. Joel West CACI, Inc. - Federal (c/o UC San Diego) {ucbvax,decvax,ihnp4}!sdcsvax!jww jww@SDCSVAX.ARPA
smb@ulysses.UUCP (Steven Bellovin) (07/23/85)
> For those keepers of the true faith who savaged my coding practices, > this is exactly my point. I designed a large software system around > the assumption that errno was always valid and not set as a side-effect. > It took me 6 months (admittedly, I wasn't looking hard) to figure out > why I was always getting "not a typewriter" (because my open routine > was setting a struct bit to indicate tty/non-tty for every file). > > My reason for posting this was to call attention to an error in the > documentation. All the manuals I've seen are in error, because this > is a known, established, important "SPECIAL CONSIDERATION". My 4.2bsd manual describes this in the INTRO(2) section, right before the list of errno values. Just where would you prefer that it be mentioned? RTFM!
campbell@maynard.UUCP (Larry Campbell) (07/25/85)
> As an aside, has anyone noticed that DEC and [name deleted] have removed the > BUGS entries from the man pages? I guess that they're afraid that non UN*X > people will think that BUGS means buggy programs, not unavoidable/historical > artifacts. DEC didn't remove the BUGS sections, they just renamed them RESTRICTIONS. They also added this line to EVERY man page: <name> is not supported by Digital Equipment Corporation. Actually there are a few commands that they do support. But not one single system call is supported! I can just hear the telephone support people (remember, the reason you bought Ultrix instead of BSD 4.2) now... "Oh, fork(2) doesn't work? Too bad. open(2)? Sorry, not supported."
alexis@reed.UUCP (Alexis Dimitriadis) (07/26/85)
> > ... I designed a large software system around > > the assumption that errno was always valid and not set as a side-effect. > > It took me 6 months (admittedly, I wasn't looking hard) to figure out > > why I was always getting "not a typewriter" (because my open routine > > was setting a struct bit to indicate tty/non-tty for every file). > > My 4.2bsd manual describes this in the INTRO(2) section, right before the > list of errno values. Just where would you prefer that it be mentioned? > RTFM! MY 4.2bsd manual says: ... An error number is also made available in the external variable _errno_, which is not cleared on successful calls. Thus _errno_ should be tested only after an error has occurred. What does "not cleared on successful calls" mean to you? To me, it means that if I set errno = 0 in the beginning of my program, it will stay zero until a system call _fails_, then it will stay non-zero long enough for me to do something about it. Now if a perfectly successful operation sets errno and does not bother to clear it, how can I depend on errno as an indication that something went _wrong_? Remember, TFM does not say anywhere that _successful_ operations set errno, which is what, in effect, happens here. Or should the whole world know how fopen() is implemented, in order to decipher errno in context? If I did not dream of this, one of the proposed standards has a passage to the effect that "function calls may set errno to arbitrary values, as long as their effect on errno is _not_ documented". In other words, don't check errno after calling a library routine unless the manual says that it sets errno to something meaningful. Sigh. Alexis Dimitriadis -- _______________________________________________ As soon as I get a full time job, the opinions expressed above will attach themselves to my employer, who will never be rid of them again. alexis @ reed ...teneron! \ ...seismo!ihnp4! - tektronix! - reed.UUCP ...decvax! /
mjs@eagle.UUCP (M.J.Shannon) (07/28/85)
> > > ... I designed a large software system around > > > the assumption that errno was always valid and not set as a side-effect. > > > It took me 6 months (admittedly, I wasn't looking hard) to figure out > > > why I was always getting "not a typewriter" (because my open routine > > > was setting a struct bit to indicate tty/non-tty for every file). > > > > My 4.2bsd manual describes this in the INTRO(2) section, right before the > > list of errno values. Just where would you prefer that it be mentioned? > > RTFM! > > MY 4.2bsd manual says: > > ... An > error number is also made available in the external variable > _errno_, which is not cleared on successful calls. Thus _errno_ > should be tested only after an error has occurred. > > What does "not cleared on successful calls" mean to you? To me, it > means that if I set errno = 0 in the beginning of my program, it will > stay zero until a system call _fails_, then it will stay non-zero long > enough for me to do something about it. Now if a perfectly successful > operation sets errno and does not bother to clear it, how can I depend > on errno as an indication that something went _wrong_? All of the routines in section 2 (system calls) have a return value which indicates that errno contains the reason why it failed. There are also some routines in section 3 which behave the same way. They are all adequately documented. The suggestion to "RTFM" is absolutely correct. You cannot depend on errno to tell you that an error occurred; it only tells you what the *last* error from one of those routines which sets errno (on detection of an error) was. A perfectly successful operation will not return an failure value, thus errno should not be consulted to see what the non-error was. > Remember, TFM does not say anywhere that _successful_ operations set > errno, which is what, in effect, happens here. Or should the whole > world know how fopen() is implemented, in order to decipher errno > in context? fopen() is not one of the routines which provides its failure reason in errno (except by accident of implementation, and then only when it does fail). > If I did not dream of this, one of the proposed standards has a passage > to the effect that "function calls may set errno to arbitrary values, > as long as their effect on errno is _not_ documented". In other words, > don't check errno after calling a library routine unless the manual says > that it sets errno to something meaningful. Sigh. No, that sentence should read: In other words, don't check errno after calling a library routine unless it returns an error indication *and* the manual says that it sets errno to something meaningful. > Alexis Dimitriadis -- Marty Shannon UUCP: ihnp4!eagle!mjs Phone: +1 201 522 6063
john@frog.UUCP (John Woods) (07/31/85)
> MY 4.2bsd manual says: > ... An > error number is also made available in the external variable > _errno_, which is not cleared on successful calls. Thus _errno_ > should be tested only after an error has occurred. > > What does "not cleared on successful calls" mean to you? To me, it > means that if I set errno = 0 in the beginning of my program, it will > stay zero until a system call _fails_, then it will stay non-zero long > enough for me to do something about it. Now if a perfectly successful > operation sets errno and does not bother to clear it, how can I depend > on errno as an indication that something went _wrong_? > You can't. For once, the UNIX manual was CRYSTAL CLEAR on something, and you even quoted it! What does "Thus _errno_ should be tested only after an error has occurred." mean to you? Repeat it softly to yourself until you either understand it or are hauled away in a butterfly net. -- John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101 ...!decvax!frog!john, ...!mit-eddie!jfw, jfw%mit-ccc@MIT-XX.ARPA
jww@sdcsvax.UUCP (Joel West) (08/03/85)
(This is becoming a tedious quasi-religious issue, but since it was my original point, I'd like to respond to some of the criticisms to it...) > > > > ... I designed a large software system around > > > > the assumption that errno was always valid and not set as a side-effect. > > > > > All of the routines in section 2 (system calls) have a return value which > indicates that errno contains the reason why it failed. There are also some > routines in section 3 which behave the same way. They are all adequately > documented. No where does the documentation explicitly say "Some routines which return successful results may, as a side-effect, set the value of errno to an arbitrary value." In addition, I would consider such cases to warrant mention in the "Special Considerations" :-) section. > The suggestion to "RTFM" is absolutely correct. You cannot depend > on errno to tell you that an error occurred; it only tells you what the *last* > error from one of those routines which sets errno (on detection of an error) > was. You are correct, the software does behave this way. The design, however, is counter-intuitive on this point. To be specific, some implementation shortcuts compromised a clean design that would have been worked with BOTH of our respective interpretations. > A perfectly successful operation will not return an failure value, thus > errno should not be consulted to see what the non-error was. > > If I did not dream of this, one of the proposed standards has a passage > > to the effect that "function calls may set errno to arbitrary values, > > as long as their effect on errno is _not_ documented". In other words, > > don't check errno after calling a library routine unless the manual says > > that it sets errno to something meaningful. Sigh. > > No, that sentence should read: > In other words, don't check errno after calling a library routine > unless it returns an error indication *and* the manual says that it > sets errno to something meaningful. If you're a defender of the cult of UNIX and its teachings, the latter is a reasonable statement. If you want clear and unambiguous documentation (which fits my definition of a printed "standard") the former is better. Joel West CACI, Inc. - Federal (c/o UC San Diego) {ucbvax,decvax,ihnp4}!sdcsvax!jww jww@SDCSVAX.ARPA
peter@graffiti.UUCP (Peter da Silva) (09/02/85)
> > No, that sentence should read: > > In other words, don't check errno after calling a library routine > > unless it returns an error indication *and* the manual says that it > > sets errno to something meaningful. errno is an indication of how the last system call failed. In most cases in section 3 this is also an indication of how the function itself failed. isatty, fopen(..., "r"), and a few other functions (not available in my short-term memory) do something other than return a failure when a system call fails. In fact that's how isatty generally works: it tries to do an lseek on the file descriptor and returns true if it fails (no flames if it does some other system call, please...). Fopen(..., "w") does an open(2) then a creat(2) (except maybe in SV) if the open fails. > If you're a defender of the cult of UNIX and its teachings, the latter > is a reasonable statement. If you want clear and unambiguous documentation > (which fits my definition of a printed "standard") the former is better. Surprise! I agree that it wouldn't be hard to clear errno on non-fatal syscall failures in section (3). There are probably people out there, however, whose code depends on errno being sacred to all but system calls. That last statement should read: "If you're trying to use the system as documented, the latter is a reasonable statement. If you're pointing out a possible error to be fixed in the next release, the former is better." From context it's hard to tell whether your original posting was a complaint or a request for help, and the writer of ">>" above obviously assumed it was the latter. Flames about "the cult of UNIX" are not informative.