Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!husc6!sri-unix!quintus!ok
From: ok@quintus.UUCP (Richard A. O'Keefe)
Newsgroups: comp.lang.c
Subject: Re: stdio error detection
Message-ID: <290@cresswell.quintus.UUCP>
Date: Fri, 27-Nov-87 19:11:18 EST
Article-I.D.: cresswel.290
Posted: Fri Nov 27 19:11:18 1987
Date-Received: Mon, 30-Nov-87 00:19:45 EST
References: <289@cresswell.quintus.UUCP> <6748@brl-smoke.ARPA>
Organization: Quintus Computer Systems, Mountain View, CA
Lines: 43
Keywords: errno fclose fopen stdio errors
Summary: bad advice

In article <6748@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn)
replied to my question about stdio error handling.
One of the things he said was
> Assuming no bugs in your code, fclose() can fail only if the stream had some
> unwritten buffered data and an I/O error occurred while writing it out.
and I'm very pleased to see this, because I'd never thought of that.
But when he says
> Again, the simplest thing is to let errno tell you.
I was disappointed, because the whole point of my message is that it
DOESN'T.  He says of this use of errno:
> True in general, but if you assume that the stdio function failed because
> some system call failed, it is fairly reliable.
No way is it reliable.  (a) I have no way of telling whether a stdio
function failed because some system call failed or for some other
reason -- that is what I was ASKING for!  (b) There is nothing to stop
a valid implementation of stdio calling some other system call after
the failed one, and that undefines errno even if the later system call
succeeds.
> In a UNIX environment, ENOMEM (or, less likely, EAGAIN) are the errno
> codes for inability to obtain more memory for the process.  If malloc()
> cannot obtain enough memory, one of these codes will be set in errno.
In SunOS 3.2 the malloc() family is explicitly defined to set errno, and
the different cases are clearly distinguished.  However, this is NOT in
the SVID, and it is NOT in any System V manual I've checked.  POSIX
(the IEEE 1003.1 standard) inherits malloc() from the C standard, which
is silent on this point.  (It says that some functions *must* set errno,
and that some functions *needn't*, but is silent about most and never
says *which* value errno is set to.)

Here at Quintus, I don't have to worry about porting my code to MS-DOS,
but in general I *do* have to worry about 4.2, 4.3, V.2, V.3, VMS, and
SAS Lattice C for MVS and VM/CMS.  Modulo the choice of setbuf, setvbuf,
or setbuffer, all these implementations of stdio look pretty close, and
I was hoping that maybe they had more in common than the manuals said.
One of the things that bothers me about fclose() is this:
	suppose f is a valid pointer to an open output stdio stream,
	but that fclose(f) returns EOF -- perhaps because of a write
	error when flushing remaining buffered output, or perhaps
	because of an unlucky interrupt (check man 2 close).
	IS f CLOSED?
When this is inside a loop processing a couple of hundred files, one
after the other, if f is *not* closed I can run out of streams despite
having taken care to close everything as soon as possible.