<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 622: behavior of filebuf dtor and close on error</title>
<meta property="og:title" content="Issue 622: behavior of filebuf dtor and close on error">
<meta property="og:description" content="C++ library issue. Status: CD1">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue622.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#CD1">CD1</a> status.</em></p>
<h3 id="622"><a href="lwg-defects.html#622">622</a>. behavior of <code>filebuf</code> dtor and <code>close</code> on error</h3>
<p><b>Section:</b> 31.10.6.4 <a href="https://wg21.link/fstream.members">[fstream.members]</a> <b>Status:</b> <a href="lwg-active.html#CD1">CD1</a>
 <b>Submitter:</b> Martin Sebor <b>Opened:</b> 2007-01-20 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all issues with</b> <a href="lwg-status.html#CD1">CD1</a> status.</p>
<p><b>Discussion:</b></p>
        <p>

<code>basic_filebuf</code>  dtor is  specified to  have  the following
straightforward effects:

        </p>
        <blockquote><p>

<i>Effects</i>:       Destroys      an      object       of      class
<code>basic_filebuf</code>. Calls <code>close()</code>.

        </p></blockquote>
        <p>

<code>close()</code> does a lot of potentially complicated processing,
including calling <code>overflow()</code> to write out the termination
sequence  (to   bring  the  output  sequence  to   its  initial  shift
state). Since  any of the  functions called during the  processing can
throw an exception, what should the  effects of an exception be on the
dtor? Should the  dtor catch and swallow it or  should it propagate it
to the caller?  The text doesn't  seem to provide any guidance in this
regard  other  than  the  general  restriction on  throwing  (but  not
propagating)  exceptions  from   destructors  of  library  classes  in
16.4.6.14 <a href="https://wg21.link/res.on.exception.handling">[res.on.exception.handling]</a>.

        </p>
        <p>

Further,  the last thing  <code>close()</code> is  specified to  do is
call <code>fclose()</code> to close the <code>FILE</code> pointer. The
last sentence of the <i>Effects</i> clause reads:

        </p>
        <blockquote><p>

...   If    any   of    the   calls   to    <code>overflow</code>   or
<code>std::fclose</code> fails then <code>close</code> fails.

        </p></blockquote>
        <p>

This  suggests that  <code>close()</code>  might be  required to  call
<code>fclose()</code>   if  and  only   if  none   of  the   calls  to
<code>overflow()</code> fails, and avoid closing the <code>FILE</code>
otherwise. This  way, if  <code>overflow()</code> failed to  flush out
the data, the caller  would have  the opportunity to  try to  flush it
again (perhaps  after trying  to deal with  whatever problem  may have
caused the failure), rather than losing it outright.

        </p>
        <p>

On the other hand,  the function's <i>Postcondition</i> specifies that
<code>is_open() ==  false</code>, which  suggests that it  should call
<code>fclose()</code>       unconditionally.       However,      since
<i>Postcondition</i> clauses  are specified for many  functions in the
standard,  including constructors  where they  obviously  cannot apply
after an  exception, it's not clear  whether this <i>Postcondition</i>
clause is intended to apply even after an exception.

        </p>
        <p>

It  might  be worth  noting  that  the  traditional behavior  (Classic
Iostreams  <code>fstream::close()</code> and  C <code>fclose()</code>)
is  to  close  the  <code>FILE</code> unconditionally,  regardless  of
errors.

        </p>

<p><i>[
See <a href="lwg-closed.html#397" title="ostream::sentry dtor throws exceptions (Status: NAD Editorial)">397</a><sup><a href="https://cplusplus.github.io/LWG/issue397" title="Latest snapshot">(i)</a></sup> and <a href="lwg-closed.html#418" title="exceptions thrown during iostream cleanup (Status: NAD)">418</a><sup><a href="https://cplusplus.github.io/LWG/issue418" title="Latest snapshot">(i)</a></sup> for related issues.
]</i></p>




<p id="res-622"><b>Proposed resolution:</b></p>
        <p>

After discussing this  on the reflector (see the  thread starting with
c++std-lib-17650) we propose that <code>close()</code> be clarified to
match the traditional behavior, that is to close the <code>FILE</code>
unconditionally,  even after  errors or  exceptions.  In  addition, we
propose the dtor description be amended so as to explicitly require it
to catch and swallow any exceptions thrown by <code>close()</code>.

        </p>
        <p>

Specifically,   we   propose   to   make  the   following   edits   in
31.10.3.4 <a href="https://wg21.link/filebuf.members">[filebuf.members]</a>:

        </p>
        <blockquote>
            <pre>

<code>basic_filebuf&lt;charT,traits&gt;* close();</code>

            </pre>
            <p>

<i>Effects</i>:  If <code>is_open()  == false</code>,  returns  a null
pointer.        If      a       put      area       exists,      calls
<code>overflow(traits::eof())</code> to flush  characters. If the last
virtual   member  function   called  on   <code>*this</code>  (between
<code>underflow</code>,  <code>overflow</code>,  <code>seekoff</code>,
and   <code>seekpos</code>)  was   <code>overflow</code>   then  calls
<code>a_codecvt.unshift</code> (possibly several times) to determine a
termination   sequence,    inserts   those   characters    and   calls
<code>overflow(traits::eof())</code>  again.  Finally<ins>, regardless
of whether  any of the preceding  calls fails or  throws an exception,
the  function</ins> <del>it</del>  closes   the  file   ("as   if"  by   calling
<code>std::fclose(file)</code>).<sup>334)</sup>  If any  of  the calls
<ins>made    by   the    function</ins><del>to   <code>overflow</code>
or</del><ins>,  including  </ins><code>std::fclose</code><ins>, </ins>
fails then <code>close</code> fails<ins>  by returning a null pointer.
If one of these calls throws an exception, the exception is caught and
rethrown after closing the file.</ins>

            </p>
        </blockquote>
        <p>

And to make the following edits in 31.10.3.2 <a href="https://wg21.link/filebuf.cons">[filebuf.cons]</a>.

        </p>
        <blockquote>
            <pre>

<code>virtual ~basic_filebuf();</code>

            </pre>
            <p>

<i>Effects</i>:       Destroys      an      object       of      class
<code>basic_filebuf&lt;charT,traits&gt;</code>.                   Calls
<code>close()</code>.    <ins>If  an   exception  occurs   during  the
destruction of the object, including the call to <code>close()</code>,
the     exception    is     caught    but     not     rethrown    (see
16.4.6.14 <a href="https://wg21.link/res.on.exception.handling">[res.on.exception.handling]</a>).</ins>

            </p>
        </blockquote>





</body>
</html>
