I wrote, quoting Leon:
>>>> most of the time people don't check the return values of their
>>>> print() calls, making the point of checking close() a bit moot
>>>> IMHO. Also, closing a valid read-only filedescriptor can't even
>>>> generate an error AFAIK.
>>> Certainly it can!!
>> Enlighten me :-)
I was gentle last time; it's worse than I previously wrote.
> The most common read(2) failure is EIO, but you can also get EINTR
> and EAGAIN. NFS failures may or may not fall under EIO; I believe
> those may give ETIMEDOUT or ECONNRESET, which can also happen on a
> regular socket.
Sun also documents close(2) as producing ENOLINK if the file descriptor
argument represent a remote machine whose link (whatever that exactly
means) is no longer active (or that).
http://docs.sun.com/app/docs/doc/816-5167/close-2?l=en&a=view
> And of course you can always get ENOBUFS, which is a real bummer.
This has *definitely* happened to me. It's really hard to get control
of your system again when this starts happening, but that doesn't mean
you should pretend it isn't there.
> So any of those will stick[i]ly set the ferror flag on the buffer,
> which will show up in the close.
This is the important point about checking print status. Because of
buffering, you cannot trust the return value of print. It does not
mean the data made it to the file. It doesn't even mean it made it
out of your buffer into the kernel's. This is why checking print is
*not sufficient* to determine the success of a print.
However, streams are set up so that their error flag gets set on any
failed I/O operation, and this sticky flag carries through until the
ultimate close, whose return reflects that. You can inspect the flag
with ferror, and you can clear it with clearerr. This is why checking
print is *not necessary* to determine the success of a print.
http://docs.sun.com/app/docs/doc/816-5167/read-2?l=en&a=view
Furthermore, Perl's close can be applied to things other than disk files.
The more obvious case is the way close on a popen()ed handle maps a
nonzero exit status from the waited for child pid into a close failure.
As for not being able to try write(2), because their filesystem seems
more prone to it than the others, the Linux close(2) manpage reminds
you of something that has always been true but more often ignored:
Not checking the return value of close() is a common but
nevertheless serious programming error. It is quite possible that
errors on a previous write(2) operation are first reported at the
final close(). Not checking the return value when closing the file
may lead to silent loss of data. This can especially be observed
with NFS and with disk quota.
A successful close does not guarantee that the data has been
successfully saved to disk, as the kernel defers writes. It is
not common for a filesystem to flush the buffers when the stream is
closed. If you need to be sure that the data is physically stored
use fsync(2). (It will depend on the disk hardware at this point.)
That's why vi(1) calls fsync(2)[*] when it's all done. One *can* do
this in Perl, with IO::Handle->sync, although I don't know who if anyone
does so.
*[aka fsync(3), fsync(3C), and related to fdatasync(2)]
One can also use O_SYNC with the open(2), that is, with Perl's sysopen.
> Even close(2) itself can fail, including through EINTR or once
> again, through EIO [from] a previously uncommitted write(2)
> having its own trouble.
Or a previous read(2), which *easily* incurs EIOs.
Not counting things like EBADF, EFAULT, EISDIR, or EINVAL, there
are still *many* possible failure modes. This is not exaustive:
read: EINTR, EIO, ENXIO, EAGAIN, EWOULDBLOCK, ENOBUFS, EDEADLK,
EBADMSG, ENOLCK, ENOLINK, EOVERFLOW, ETIMEDOUT, ECONNRESET
write: EINTR, EIO, ENXIO, EAGAIN, EWOULDBLOCK, ENOBUFS, EDEADLK,
EDQUOT, EFBIG, ENOLCK, ENOSPC, ENOSR, ERANGE, ENETDOWN,
ENETUNREACH, EPIPE, EDESTADDRREQ
fsync: EINTR, EIO, EROFS, ENOSPC, ETIMEDOUT, plus: "If a queued
I/O operation fails, fsync() may fail with any of the
errors defined for read(2) or write(2)."
close: EINTR, EIO, ENOLINK, plus any lingering read/write errors
from the previous three lists.
Those are merged lists gathered from OpenBSD, Sun, Apple, and Linux
(only), and I still may have missed some.
One key point here is that even if you pretend nothing else matters--
utterly foolish though that would be--the pesky EIO is *always* a
possibility of ruining your day. Bad disk, anybody? *That* never
happens, eh? :(
So Leon, are you "enlightened"? Still think you can *ever* safely
ignore close errors, even on files "merely" opened O_RDONLY? :)
--tom