[comp.unix.programmer] sscanf always generates error condition

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!