Topic: Closing file(s) in basic_filebuf dtor problematic on Linux


Author: Hyman Rosen <hyrosen@mail.com>
Date: Sat, 27 Jul 2002 17:50:20 GMT
Raw View
Alexander Sieb wrote:
> As I read the Standard, basic_filebuf::~basic_filebuf is supposed to close
> the file if it hasn't been done before. But nothing is being said about
> what should happen if the underlying system call close(2) fails.

Rather, 27.8.1.2/3 says that close() is called, so nothing is done
even if close() fails.

> If close(2) indicates an io error and you rely on
> automatic resource management of e.g. ofstream you
 > can end up with a corrupted file.

No. If close() indicates an I/O error, then you already
have a corrupted file. Checking for the error just notifies
you that this is the case - there is nothing you can do to
make the file good, except to rewrite it.

> So is it possible to change the Standard to handle this situation without
> breaking existing applications?
>
> IMHO, the only solution at the moment is to make sure a file stream has been
> closed before its dtor is being called.

This has always been the solution, and does not require any fixing.
If you want to handle the possibility of close failing, call close
yourself and check for failure. This is true of any other RAII type
as well; if the release of the resource can fail and requires action
to correct the failure, you need to call a release method explicitly
and check for the error.

For your own classes, just call close explicitly in your destructors
on any ofstreams that you use. Then you can check for failure and do
whatever you like.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Alexander Sieb <sieb@sscd.de>
Date: Thu, 25 Jul 2002 23:58:58 GMT
Raw View
Hi everybody,

it is hopefully^W well known that ignoring the return value of close(2) i=
s  a
programming error on Linux. The close(2) man page describes it as follows=
:

<quote>
NOTES
       Not checking the return value of close is a common  but  neverthe=AD
       less serious programming error.  File system implementations which
       use techniques as ``write-behind''  to  increase  performance  may
       lead  to write(2) succeeding, although the data has not been writ=AD
       ten yet.  The error status may be reported at a later write opera=AD
       tion,  but  it  is  guaranteed to be reported on closing the file.
       Not checking the return value when closing the file  may  lead  to
       silent loss of data.  This can especially be observed with NFS and
       disk quotas.

       A successful close does not guarantee that the data has been  suc=AD
       cessfully  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) or sync(2), they will get you closer to that goal (it
       will depend on the disk hardware at this point).
</quote>

The same is probably true for other operating systems but not documented.=
 I'm
writing about Linux here.

Now what happens if close(2) is called from within a dtor and returns EIO=
?
How can an application find out that not all data has made it to the
filesystem? (Note: Even if no error is reported in user space, a million =
things
can go wrong in kernel space before your data *really* hits the platters =
of
your HDD. But that's a totally different story)

As I read the Standard, basic_filebuf::~basic_filebuf is supposed to clos=
e
the file if it hasn't been done before. But nothing is being said about
what should happen if the underlying system call close(2) fails.

I checked STLport and libstdc++-v3 (from gcc 3.1) and none of them handle=
s
this specific problem. If close(2) indicates an io error and you rely on
automatic resource management of e.g. ofstream you can end up with a corr=
upted
file.

So is it possible to change the Standard to handle this situation without
breaking existing applications?=20

IMHO, the only solution at the moment is to make sure a file stream has b=
een
closed before its dtor is being called.=20

Ideas anybody?

PS: What happens if an application's cout is redirected to a file located=
 on
a NFS mounted filesystem, but cout.close() fails?

--=20
Regards,
 Alexander

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]