Uploaded image for project: 'C++ Standard Library'
  1. C++ Standard Library
  2. STDCXX-308

[LWG #622] std::filebuf dtor doesn't close fd after exception

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 4.1.2, 4.1.3, 4.1.4, 4.2.0
    • 4.2.1
    • 27. Input/Output
    • None
    • all

    • Incorrect Behavior

    Description

      -------- Original Message --------
      Subject: Re: aCC 3.70 -AA fd's close not being called.
      Date: Thu, 7 Dec 2006 23:17:55 -0800 (PST)
      From: Dennis Handly <dhandly@cup.hp.com>
      To: sebor@roguewave.com
      CC: Boris.Gubenko@hp.com, al.simons@hp.com, dhandly@cup.hp.com

      It appears this problem is still in the apache code:
      http://svn.apache.org/repos/asf/incubator/stdcxx/trunk/include/fstream.cc

      It seems to violate 27.8.1.3(6), which says it always "finally" calls
      "as if" fclose(3). And returns an error if any calls fail.

      ================================================================
      >From: "Levie, Barry" <barry.levie@hp.com>
      Date: Thu, 7 Dec 2006 15:36:33 -0000
      Subject: aCC 3.70 -AA fd's close not being called.

      I am not sure if this exactly represents the problem the customer is
      having as I am still waiting for more details (versions/test case etc
      etc). However this could be close and I think it shows a problem.

      Why does the ofstream destructor not close the file descriptor when its
      called after its thrown an exception for "out of disk space".

      This aCC 3.70 -AA example shows an ever increasing number of open file
      descriptors in glance

      1. what /usr/lib/libstd_v2.2:
        HP aC++ B3910B A.03.30 C++ Standard Library (RogueWave Version 2.02.01)

      #include <iostream>
      #include <fstream>
      #include <string.h>
      using namespace std;
      struct dummy {
      dummy()

      { cout << "\ndummy created \n" ;}

      ~dummy()

      { cout << "\ndummy deleted \n"; }

      };
      void bar() {
      char buf[1024*1024];
      memset(buf,'A',1024*1024);
      buf[1024*1024 -1] = 0;
      ofstream of;
      dummy df;
      of.exceptions(ofstream::eofbit | ofstream::failbit | ofstream::badbit);
      try {
      of.open("/home/test.txt"); // this is on a volume that is nearly full.
      while(1)

      { of << buf; }

      }
      catch(ofstream::failure& e)

      { cout << "\nException write/file"; }

      }
      int main () {
      while(1) bar();
      }

      1. ./a.out

      dummy created
      msgcnt 160 vxfs: mesg 001: vx_nospace - /dev/vg00/lvol5 file system full
      (1 block extent)
      Exception write/file
      dummy deleted
      ....

      Glance output shows

      D File Name Type Mode Count Offset
      ---------------------------------------------------
      0 /dev/pts/ta stream rd/wr 6 333822
      1 /dev/pts/ta stream rd/wr 6 333822
      2 /dev/pts/ta stream rd/wr 6 333822
      3 /home/test.txt reg write 1 101957632
      4 /home/test.txt reg write 1 101957632
      5 /home/test.txt reg write 1 101957632
      ...
      ================================================================
      >From: Dennis Handly <dhandly@cup.hp.com>
      Date: Thu, 7 Dec 2006 23:03:08 -0800 (PST)
      To: acxx@cup.hp.com, barry.levie@hp.com
      Subject: Re: aCC 3.70 -AA fd's close not being called.

      >From: "Levie, Barry" <barry.levie@hp.com>
      >I am not sure if this exactly represents the problem the customer is
      >having as I am still waiting for more details (versions/test case etc
      >etc). However this could be close and I think it shows a problem.

      >Why does the ofstream destructor not close the file descriptor when its
      >called after its thrown an exception for "out of disk space".

      A highly modified version works for me.
      And it isn't closed on the throw but by falling off the bar body.

      >This aCC 3.70 -AA example shows an ever increasing number of open file
      >descriptors in glance

      Hmm.

      ># what /usr/lib/libstd_v2.2:
      > HP aC++ B3910B A.03.30 C++ Standard Library (RogueWave Version 2.02.01)

      This obsolete version isn't supported.

      Here is what I have and it shows close being called after I throw.

      I've manually modified the write return to -1 and that throws and is caught.
      (The debugger was broken and it didn't really happen. )-:

      #include <iostream>
      #include <fstream>
      #include <string.h>
      #include <stdio.h>
      using namespace std;
      struct dummy {
      dummy()

      { fprintf(stdout, "dummy created\n"); fflush(stdout); }

      ~dummy()

      { fprintf(stdout, "dummy deleted\n"); fflush(stdout); }

      };
      extern "C" int _close(int fd);
      extern "C" int close(int fd) {
      if (fd > STDERR_FILENO)

      { fprintf(stdout, "close(%d)\n", fd); fflush(stdout); }

      return _close(fd);
      }
      char buf[1024];
      void bar() {
      ofstream of;
      dummy df;
      of.exceptions(ofstream::eofbit | ofstream::failbit | ofstream::badbit);
      try

      { of.open("test.txt"); // this is on a volume that is nearly full. fprintf(stdout, "FD = %d\n", of.rdbuf()->fd()); fflush(stdout); for (int i = 0; i < 2; ++i) of << buf; throw ios_base::failure(); }

      catch(ofstream::failure &e)

      { fprintf(stdout, "Exception write/file\n"); fflush(stdout); }

      }
      int main() {
      memset(buf,'A',sizeof(buf));
      buf[sizeof(buf)-1] = '\0';
      int i;
      for (i = 0; i < 10; ++i)
      bar();
      }

      Ah, it's catch 22. When it destroys ofstream it calls close, which calls
      overflow which calls _C_write which calls write which gets an error and
      then returns before closing.

      It seems it is working as designed be RW.

      But this seems to violate 27.8.1.3(6), which says it always calls
      fclose(3).

      File a CR.

      Attachments

        Activity

          People

            sebor Martin Sebor
            sebor Martin Sebor
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Time Tracking

                Estimated:
                Original Estimate - 4h Original Estimate - 4h
                4h
                Remaining:
                Remaining Estimate - 0h
                0h
                Logged:
                Time Spent - 6h
                6h