ilan343@violet.berkeley.edu (Geraldo Veiga) (05/01/91)
Is there a good reason why "sscanf" under ISC 2.2 always sets
"errno=9" even though it executed successfully?
This is an example:
#include <stdio.h>
extern int errno;
char s[] = "10000";
main ()
{
int tmp;
sscanf(s,"%d",&tmp);
perror("System error");
}
This is the output of the above code:
System error: Bad file number
(This message corresponds to errno=9)
If this a bug? BSD's sscanf doesn't display this behavior.
hunt@dg-rtp.rtp.dg.com (Greg Hunt) (05/01/91)
In article <1991Apr30.233554.1321@agate.berkeley.edu>, ilan343@violet.berkeley.edu (Geraldo Veiga) writes: > Is there a good reason why "sscanf" under ISC 2.2 always sets > "errno=9" even though it executed successfully? > > This is an example: > > #include <stdio.h> > extern int errno; > char s[] = "10000"; > main () > { > int tmp; > sscanf(s,"%d",&tmp); > perror("System error"); > } > > This is the output of the above code: > > System error: Bad file number > (This message corresponds to errno=9) > > If this a bug? BSD's sscanf doesn't display this behavior. Yup, it's a bug. But it's a bug in your code, not sscanf. Errno is not set on successful conclusion of calls, only on ones that encountered an error. So, before looking at errno, you have to check the return value from whatever you were doing to determine if an error occurred. On system calls, the return value for success is usually zero, and the return value for failure is usually -1. You have to read the man page for the calls, though, because some return other things on success in particular (as is true for sscanf). Since your example discards the return value from sscanf, you can't test it to see if some error occurred before you look at errno. In the test case, errno is being used without having a value assigned to it, so the "9" is just garbage that happened to be in the memory associated with errno at the time. On the other system you tried, the garbage happened to have been zero, so everything worked. You can see that this is what is happening by adding a line like "errno = 25;" right before sscanf. Then the "error" you'll get will be "Not a typewriter"! This will prove that sscanf is not setting errno on a successful conclusion. Take a closer look at the man page for sscanf, particularly the parts describing the return value. You'll need to change your code to capture the return value in a variable, and then test it to see if an error occurred. If so, then call perror. Don't call it otherwise. This is a pretty common mistake to make, so don't feel bad about it. It's not intuitive, is it? You'd think that errno would be set to zero if the call works, but that's not done for performance reasons. The return value from calls is always set properly when they return, and that is what you have to test first to see if an error occurred. Also take a look at the man page on errno, or perror, for more info on how errno is handled. Good luck! -- Greg Hunt Internet: hunt@dg-rtp.rtp.dg.com DG/UX Kernel Development UUCP: {world}!mcnc!rti!dg-rtp!hunt Data General Corporation Research Triangle Park, NC, USA These opinions are mine, not DG's.
jik@athena.mit.edu (Jonathan I. Kamens) (05/01/91)
In article <1991Apr30.233554.1321@agate.berkeley.edu>, ilan343@violet.berkeley.edu (Geraldo Veiga) writes: |> #include <stdio.h> |> extern int errno; |> char s[] = "10000"; |> main () |> { |> int tmp; |> sscanf(s,"%d",&tmp); |> perror("System error"); |> } You are violating two rules of Unix programming here. First of all, system calls are allowed to set errno to whatever they want, even if they return successfully. The only time you are supposed to check errno is if a library function has signaled to you that it is returning abnormally. Therefore, the body of your program should be replaced by: int tmp, retval; retval = sscanf(s, "%d", &tmp); if (retval == EOF) { fprintf(stderr, "Short string.\n"); else if (retval != 1) { perror("System error"); Remember that sscanf returns the number of variables assigned, or EOF on end of file (or, in the case of sscanf, a short string) or file error. Second, technically speaking, the only time errno is relevant is when a system call fails. This means that, in the strictest sense, it is not valid to use errno to find out what error occurred after a library function fails. However, in cases where you know that the library function failed because of a failed system call, it's a good bet that errno will still contain the error return value from the system call, so it's usually OK to use it to determine what happened. -- Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8085 Home: 617-782-0710
ilan343@violet.berkeley.edu (Geraldo Veiga) (05/02/91)
First of all, thank you for all postings and mail helping me with this question. In article <1991May1.024357.7750@dg-rtp.dg.com> hunt@dg-rtp.rtp.dg.com writes: >Errno is not set on successful conclusion of calls, only on ones that >encountered an error. Ok. >Since your example discards the return value from sscanf, you can't >test it to see if some error occurred before you look at errno. In >the test case, errno is being used without having a value assigned to >it, so the "9" is just garbage that happened to be in the memory >associated with errno at the time. On the other system you tried, the >garbage happened to have been zero, so everything worked. This was not the case. In the ISC system call errno=0 (or whatever I set it to) before and errno=9 after. Also, sscanf returns 1 (as it should in my example). >Take a closer look at the man page for sscanf, particularly the parts >describing the return value. You'll need to change your code to >capture the return value in a variable, and then test it to see if >an error occurred. If so, then call perror. Don't call it otherwise. This problem came up because I have a generic error message function used for both system and user errors. This function always checks the value of errno and prints whatever system error message was indicated (with a perror() call). From the discussion in this and one previous posting, this doesn't seem a like very good idea, since a system call could set the value of errno to some misleading value that would generate a non-related message next time I print a user error message. >This is a pretty common mistake to make, so don't feel bad about it. >It's not intuitive, is it? You'd think that errno would be set to >zero if the call works, but that's not done for performance reasons. I was aware that the it wouldn't set errno=0, but setting it to a non-zero value on normal termination still bothers me.
hunt@dg-rtp.rtp.dg.com (Greg Hunt) (05/02/91)
In article <1991May1.193252.16232@agate.berkeley.edu>, ilan343@violet.berkeley.edu (Geraldo Veiga) writes: > First of all, thank you for all postings and mail helping me with > this question. You're welcome. Me>In the test case, errno is being used without having a value assigned to Me>it, so the "9" is just garbage that happened to be in the memory Me>associated with errno at the time. On the other system you tried, the Me>garbage happened to have been zero, so everything worked. GV> This was not the case. In the ISC system call errno=0 (or whatever I GV> set it to) before and errno=9 after. Also, sscanf returns 1 GV> (as it should in my example). That's wierd. Since the return value is correct, then I would guess that the errno being set to 9 is meaningless. I would have expected it to not be set at all, however. Obviously on the ISC system, it's being handled differently. GV> This problem came up because I have a generic error message function GV> used for both system and user errors. This function always checks the GV> value of errno and prints whatever system error message was indicated GV> (with a perror() call). GV> GV> From the discussion in this and one previous posting, this doesn't seem GV> a like very good idea, since a system call could set the value of errno GV> to some misleading value that would generate a non-related message GV> next time I print a user error message. The common error handling is a great idea! Don't throw it away! Just change the code after a system call or library call to check the return value to detect if an error occurred first, then call your common error handler to print the error out (and shutdown the process, or whatever else it does). This is exactly how I use the common error handler that I have in my own code, and it works great. GV> I was aware that the it wouldn't set errno=0, but setting it to a GV> non-zero value on normal termination still bothers me. It would bother me, too. It might be a bug in the ISC sscanf library call (albeit a fairly harmless one since the function works and does return the proper value). If you're inclined to do so, you might want to check with them about it. Giving them your test case that shows errno is being reset would help them track it down to determine if it really is a bug, or whether it's supposed to be happening. -- Greg Hunt Internet: hunt@dg-rtp.rtp.dg.com DG/UX Kernel Development UUCP: {world}!mcnc!rti!dg-rtp!hunt Data General Corporation Research Triangle Park, NC, USA These opinions are mine, not DG's.
jik@athena.mit.edu (Jonathan I. Kamens) (05/03/91)
In article <1991May2.134354.9719@dg-rtp.dg.com>, hunt@dg-rtp.rtp.dg.com (Greg Hunt) writes: |> GV> I was aware that the it wouldn't set errno=0, but setting it to a |> GV> non-zero value on normal termination still bothers me. |> |> It would bother me, too. It might be a bug in the ISC sscanf library |> call (albeit a fairly harmless one since the function works and does |> return the proper value). It is *not* a bug. The specification of the system call interface is that if a system call succeeds, errno is irrelevant, and its value is undefined. The value is only defined if the system call fails. There are quite a few system calls in the kernel that set errno to a value, then try the operation which would cause that error value if it failed, and then return immediately it it fails, signalling an error. They're allowed to do that. You cannot count on the value of errno being zero if a function succeeds. That's the way the system call interface is designed, and, in all likelihood, that design is ingrained in too many different systems for it to be changed in the foreseeable future. -- Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8085 Home: 617-782-0710
ilan343@violet.berkeley.edu (Geraldo Veiga) (05/04/91)
In article <1991May3.095541.21439@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes: > There are quite a few system calls in the kernel that set errno to a value, >then try the operation which would cause that error value if it failed, and >then return immediately it it fails, signalling an error. They're allowed to >do that. > This seems to be the final word on this question. From now on I'll have two separate error handling routines: syserr(message) invoked only when a system call returns an error condition. This function prints "message", calls perror() and exits. usrerr(message) invoked for non-system errors, same as above without the call to perror(). Thanks for everybody's help.
scs@adam.mit.edu (Steve Summit) (05/07/91)
In article <1991May1.024357.7750@dg-rtp.dg.com> hunt@dg-rtp.rtp.dg.com writes: >In article <1991Apr30.233554.1321@agate.berkeley.edu>, ilan343@violet.berkeley.edu (Geraldo Veiga) writes: >> System error: Bad file number >> (This message corresponds to errno=9) > >In the test case, errno is being used without having a value assigned to >it, so the "9" is just garbage that happened to be in the memory >associated with errno at the time. Actually, "Bad file number" is an extremely likely inadvertent errno value after a successful call to sscanf, and not because of any random memory contents. sscanf (and, equivalently, sprintf) work by setting up a temporary buffered file descriptor (FILE *) which uses as its I/O buffer the user's string. When the string is exhausted, the stdio code typically falls into the same buffer refilling code (often an internal routine called _filbuf) which attempts to read more data from the associated file into the buffer. The low- level file descriptor for a string pseudo-file is usually set to -1, so the read fails, with EBADF. (This error ends up looking like EOF, which is what we'd want to happen at the end of the sscanf string anyway. Actually, ferror() would probably report that an error had occurred, except that by the time sscanf has returned, the temporary FILE *, and its error indication, has disappeared.) BSD systems (and probably many others) set the internal _IOSTRG flag on string pseudo-files, which can be used to avoid an inadvertent read or write to a bad file descriptor in these cases. As has been (correctly) pointed out, however, it's not incorrect for ISC's sscanf to be leaving EBADF in errno, because (to quote from an old version of the comp.lang.c frequently-asked questions list), "it is only meaningful for a program to inspect the contents of errno after an error has occurred (that is, after a library function that sets errno on error has returned an error code)." (The more common guise under which this issue comes up is "Why does errno contain ENOTTY after a call to printf?") Steve Summit scs@adam.mit.edu
clewis@ferret.ocunix.on.ca (Chris Lewis) (05/07/91)
In article <1991May7.020259.3646@athena.mit.edu> scs@adam.mit.edu writes: >As has been (correctly) pointed out, however, it's not incorrect >for ISC's sscanf to be leaving EBADF in errno, because (to quote >from an old version of the comp.lang.c frequently-asked questions >list), "it is only meaningful for a program to inspect the >contents of errno after an error has occurred (that is, after a >library function that sets errno on error has returned an error ^^^^^^^^^^^^^^^^ >code)." The underlined phrase should be "system call". Library routines can return an error yet the errno won't indicate the real reason for the failure. Most modern versions of the manual pages document exactly which system calls set the errno, and describe the causes for each one. Ie: "errno is only relevant when a system call that is documented to set errno indicates an error has occured by its return value". (The more common guise under which this issue comes up >is "Why does errno contain ENOTTY after a call to printf?") > Steve Summit > scs@adam.mit.edu Put the way this usually crops up: "Why did your sendmail bounce my mail with a: 550 ... Not a tty message" ;-) -- Chris Lewis, Phone: (613) 832-0541, Domain: clewis@ferret.ocunix.on.ca UUCP: ...!cunews!latour!ecicrl!clewis; Ferret Mailing List: ferret-request@eci386; Psroff (not Adobe Transcript) enquiries: psroff-request@eci386 or Canada 416-832-0541. Psroff 3.0 in c.s.u soon!
scs@adam.mit.edu (Steve Summit) (05/09/91)
In article <1474@ecicrl.ocunix.on.ca> clewis@ferret.ocunix.on.ca (Chris Lewis) writes: >In article <1991May7.020259.3646@athena.mit.edu> scs@adam.mit.edu writes: >>(to quote >>from an old version of the comp.lang.c frequently-asked questions >>list), "it is only meaningful for a program to inspect the >>contents of errno after an error has occurred (that is, after a >>library function that sets errno on error has returned an error > ^^^^^^^^^^^^^^^^ >>code)." > >The underlined phrase should be "system call". Library routines >can return an error yet the errno won't indicate the real reason >for the failure. It's hard to word correctly. I had revised it several times, and it still wasn't perfect. It can't just say "system call," however, because a few library routines (e.g. many of the math routines) *are* documented as setting errno. There are also non-Unix systems which have emulators for Unix system calls present in the C library. Finally, since system calls themselves are invariably accessed through tiny routines also present in "the library" (i.e. /lib/libc.a), I cheated and talked about "library routine[s] that set errno on error." I would not have been so cavalier in a Unix FAQ list. >(The more common guise under which this issue comes up >>is "Why does errno contain ENOTTY after a call to printf?") > >Put the way this usually crops up: "Why did your sendmail bounce >my mail with a: > 550 ... Not a tty >message" ;-) Indeed. (I'd forgotten the "real" question; thanks for the reminder.) Steve Summit scs@adam.mit.edu
jc@minya.UUCP (John Chambers) (05/17/91)
In article <1991May1.050122.21795@athena.mit.edu>, jik@athena.mit.edu (Jonathan I. Kamens) writes: > > Second, technically speaking, the only time errno is relevant is when a > system call fails. This means that, in the strictest sense, it is not valid > to use errno to find out what error occurred after a library function fails. > However, in cases where you know that the library function failed because of a > failed system call, it's a good bet that errno will still contain the error > return value from the system call, so it's usually OK to use it to determine > what happened. Well, gee, I've written lots of routines that do things like: if (f < 0 || f > maxfile) { errno = EBADF; return -1; } I've recently seen a lot of suggestions, including the above, that I am violating some rules that I've never seen documented. It seems that the naive programmer is highly likely to assume that such practices are not only legal, but encouraged. Now I find that some people think that errno is not legal for me to use, even when it does the job quite elegantly. So if I'm not allowed to mimic the system calls in such a case, what should I do? Should I set up a new global variable to hold the error code for each routine, and make up my own error codes for each one? Sure, I can do this, but it doesn't seem like a very friendly thing to do to the poor suckers who use my routines. So what are the rules? Is errno truly global, or is it supposed to be private to libc? Where is it documented and specified that I am forbidden to use it in the obvious way, that I should have known about it? -- All opinions Copyright (c) 1991 by John Chambers. Inquire for licensing at: Home: 1-617-484-6393 Work: 1-508-486-5475 Uucp: ...!{bu.edu,harvard.edu,ima.com,eddie.mit.edu,ora.com}!minya!jc
clewis@ferret.ocunix.on.ca (Chris Lewis) (05/18/91)
In article <785@minya.UUCP> jc@minya.UUCP (John Chambers) writes: >In article <1991May1.050122.21795@athena.mit.edu>, jik@athena.mit.edu (Jonathan I. Kamens) writes: >> Second, technically speaking, the only time errno is relevant is when a >> system call fails. This means that, in the strictest sense, it is not valid >> to use errno to find out what error occurred after a library function fails. >> However, in cases where you know that the library function failed because of a >> failed system call, it's a good bet that errno will still contain the error >> return value from the system call, so it's usually OK to use it to determine >> what happened. >Well, gee, I've written lots of routines that do things like: > if (f < 0 || f > maxfile) { > errno = EBADF; > return -1; > } >I've recently seen a lot of suggestions, including the above, that I am >violating some rules that I've never seen documented. It seems that the >naive programmer is highly likely to assume that such practices are not >only legal, but encouraged. Now I find that some people think that errno >is not legal for me to use, even when it does the job quite elegantly. >So if I'm not allowed to mimic the system calls in such a case, what should >I do? Should I set up a new global variable to hold the error code for each >routine, and make up my own error codes for each one? Sure, I can do this, >but it doesn't seem like a very friendly thing to do to the poor suckers who >use my routines. >So what are the rules? Is errno truly global, or is it supposed to be >private to libc? Where is it documented and specified that I am forbidden >to use it in the obvious way, that I should have known about it? I think you misunderstand. The correct interpretation of the manuals is that you can't rely on the value of errno after invoking a function (whether system call or real function) *unless* the manual page for the function *documents* that the value of errno is set on error, and that the function has actually returned an error. I've not seen documentation saying that you cannot set errno yourself. For example, go look at the manual page for open(). It will probably give a list of what conditions lead to the errno being set, and what it'll be set to. Therefore, if (open(...) < 0) you can inspect errno and be guaranteed that errno is relevant to the real error. On the other hand, for printf(), there is no documented settings for errno, thus errno cannot be trusted to mean anything relevant if printf() returns an error. I say "system call or function" *because* some functions are documented to set errno. Sometimes because they're emulating a system call (eg: various flavors of exec), and sometimes because the original definition did. Further, many functions that aren't documented to set errno on error, *may* invoke something that does (depending on implementation specifics), and the errno setting may have *nothing* to do whatsoever with the function you actually called. Ie: the infamous "not a tty" or "invalid ioctl on device" errno after a printf(). I've never seen anything prohibiting you from setting errno in a function of your own and testing it. However, you must be cautious that anything you invoke between the time you set errno and the time you test it doesn't clobber errno. Ie this is dangerous: if (f < 0 || f > maxfile) { errno = EBADF; fprintf(stderr, "You goofed\n"); return -1; } Swap the order of the fprintf and the errno assignment and it'll be safe as far as I know. [Some systems might just make the errno read-only but I don't know of any. I know that some systems have errno at an absolute address near the top of the user's stack. Others have it at a special absolute place in the image's data space. Still others inlined it in the text area - but those didn't have readonly text.] -- Chris Lewis, Phone: (613) 832-0541, Domain: clewis@ferret.ocunix.on.ca UUCP: ...!cunews!latour!ecicrl!clewis; Ferret Mailing List: ferret-request@eci386; Psroff (not Adobe Transcript) enquiries: psroff-request@eci386 or Canada 416-832-0541. Psroff 3.0 in c.s.u soon!