CBufferedFile: convert into a non-refcounted RAII wrapper #4978

pull Diapolo wants to merge 3 commits into bitcoin:master from Diapolo:fix_fclose changing 2 files +41 −16
  1. Diapolo commented at 6:57 AM on September 25, 2014: none
    • it now takes over the passed file descriptor and closes it in the destructor
    • this fixes a leak in LoadExternalBlockFile(), where an exception could cause the file to not getting closed
    • disallow copies (like recently added for CAutoFile)
    • make nType and nVersion private
  2. laanwj commented at 7:07 AM on September 25, 2014: member

    I'd say we need something more RAII-ish here.

    Easiest would be to make CBufferedFile take ownership of the FILE* - ie, close it on destruction, like CAutoFile. This is the only place CBufferedFile is used so there would be no other impact.

  3. Diapolo commented at 7:25 AM on September 25, 2014: none

    @laanwj You also could have been saying "Hey, nice catch, but..." :-P. I agree on your suggestion anyway.

  4. laanwj commented at 7:29 AM on September 25, 2014: member

    Yes, nice catch that there is a potential leak here!

    I just don't think the current solution solves it completely. Other exceptions that are not directly catched will still cause the file not to be closed.

  5. Diapolo renamed this:
    add missing fclose on exception in LoadExternalBlockFile()
    convert CBufferedFile into a RAII wrapper
    on Sep 25, 2014
  6. Diapolo commented at 12:07 PM on September 25, 2014: none

    @laanwj Converted to a RAII-style wrapper and removed the manual fclose().

  7. laanwj commented at 12:11 PM on September 25, 2014: member

    Looks good to me now.

  8. theuni commented at 7:55 PM on September 25, 2014: member

    You may want to make a note here that CBufferedFile is non-refcounted. Not a huge deal since there's only one user of it now, but I suppose that could change. Problem would be (stupid example):

    CBufferedFile foo(fd,...);
    {
        CBufferedFile bar(fd2,...);
        foo=bar;
    }
    foo.read(...)
    
  9. Diapolo commented at 8:53 PM on September 25, 2014: none

    @theuni Should I place that comment in serialize.h above the class?

  10. theuni commented at 9:48 PM on September 25, 2014: member

    @Diapolo sounds good. Probably not a bad idea to make the copy ctor and operator= private for good measure.

  11. theuni commented at 11:28 PM on September 25, 2014: member

    @Diapolo I took a look at CAutoFile and it has the same behavior. See #4986.

  12. in src/serialize.h:None in 9576d8e2ef outdated
    1298 | +        fclose();
    1299 | +    }
    1300 | +
    1301 | +    void fclose()
    1302 | +    {
    1303 | +        if (src != NULL && src != stdin && src != stdout && src != stderr)
    


    sipa commented at 6:38 PM on September 26, 2014:

    ewww


    Diapolo commented at 11:33 AM on September 27, 2014:

    @sipa I took that from CAutoFile and can't interpret your comment. Should I just directly do this in the destructor?

    <pre> if (src) fclose(src); </pre>


    laanwj commented at 2:04 PM on September 27, 2014:

    Agreed, and I'd say remove it from CAutoFile as well


    sipa commented at 5:41 PM on September 27, 2014:

    Agree.

  13. Diapolo renamed this:
    convert CBufferedFile into a RAII wrapper
    convert CBufferedFile into a non-refcounted RAII wrapper
    on Sep 28, 2014
  14. Diapolo commented at 1:41 PM on September 28, 2014: none

    Updated to include:

    • update CAutoFile destructor to match CBufferdFile destructor
    • CBufferedFile: make src protected, nType and nVersion private
    • CAutoFile: make nType and nVersion private
  15. laanwj commented at 12:59 PM on September 29, 2014: member

    That's a lot of red...

  16. Diapolo commented at 1:17 PM on September 29, 2014: none

    @laanwj I didn't check the Travis build :-/. It was caused by the now missing CAutoFile::fclose() function, which was called by CAddrDB explicitly. I removed them now as it seemed save to me. We may aswell add a CAutoFile::close() instead to still allow closing a file explicitly.

  17. laanwj commented at 1:24 PM on September 29, 2014: member

    Well IMO it's fine to have a method to close the file explicitly, but it should be optional, so if the object goes out of scope the file is closed nevertheless.

  18. Diapolo commented at 2:12 PM on September 29, 2014: none

    Now it's green :). Shall I add an explicit close() to CAutoFile and CBufferedFile via this pull? Btw. can you first verify, if the current changes are correct perhaps :-D?

    Edit: Since the commits are rather easy to review, I added the close() as a fifth commit.

  19. BitcoinPullTester commented at 7:33 PM on September 29, 2014: none

    Automatic sanity-testing: FAILED BUILD/TEST, see http://jenkins.bluematt.me/pull-tester/p4978_d26ef84ff33bc384671bf9b18b0fd2018ec339f2/ for binaries and test log.

    This could happen for one of several reasons:

    1. It chanages paths in makefile.linux-mingw or otherwise changes build scripts in a way that made them incompatible with the automated testing scripts (please tweak those patches in qa/pull-tester)
    2. It adds/modifies tests which test network rules (thanks for doing that), which conflicts with a patch applied at test time
    3. It does not build on either Linux i386 or Win32 (via MinGW cross compile)
    4. The test suite fails on either Linux i386 or Win32
    5. The block test-cases failed (lookup the first bNN identifier which failed in https://github.com/TheBlueMatt/test-scripts/blob/master/FullBlockTestGenerator.java)

    If you believe this to be in error, please ping BlueMatt on freenode or TheBlueMatt here.

    This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/ Contact BlueMatt on freenode if something looks broken.

  20. Diapolo commented at 1:28 PM on October 1, 2014: none

    @laanwj Green, finally... wohooo!

  21. theuni commented at 12:19 AM on October 2, 2014: member

    Why are the File*'s left protected? Keeping anything protected is just inviting inheritance, which would surely be disastrous for these. I'd make em private.

  22. sipa commented at 2:04 AM on October 2, 2014: member

    Agree with @theuni.

  23. in src/net.cpp:None in cec44913e8 outdated
    1968 | @@ -1969,7 +1969,6 @@ bool CAddrDB::Write(const CAddrMan& addr)
    1969 |          return error("%s : Serialize or I/O error - %s", __func__, e.what());
    1970 |      }
    1971 |      FileCommit(fileout);
    1972 | -    fileout.fclose();
    


    laanwj commented at 7:58 AM on October 2, 2014:

    Keep this explicit fclose; we do a rename after it, that's a valid reason to want it closed. (either that, or make sure it is out of scope)


    Diapolo commented at 8:36 AM on October 2, 2014:

    Yeah makes sense.

  24. Diapolo commented at 8:35 AM on October 2, 2014: none

    @theuni @sipa I changed them back to private for CBufferedFile and also made FILE* private for CAutoFile. Thanks for your feedback. If I get some ACKs I'll squash the commits to be not 5, but rather 2 I guess.

  25. CBufferedFile: convert into a non-refcounted RAII wrapper
    - it now takes over the passed file descriptor and closes it in the
      destructor
    - this fixes a leak in LoadExternalBlockFile(), where an exception could
      cause the file to not getting closed
    
    - disallow copies (like recently added for CAutoFile)
    - make nType and nVersion private
    c9fb27da0a
  26. CBufferedFile: add explicit close function
    - also use identical close function for CAutoFile (avoids setting file to
      NULL under wrong conditions)
    0c35486dc9
  27. CAutoFile: make file private 938bccebf1
  28. Diapolo renamed this:
    convert CBufferedFile into a non-refcounted RAII wrapper
    CBufferedFile: convert into a non-refcounted RAII wrapper
    on Oct 2, 2014
  29. Diapolo commented at 9:03 AM on October 2, 2014: none

    @laanwj Squashed into 3 much more logical commits now.

  30. laanwj commented at 9:53 AM on October 2, 2014: member

    Looks good to me now. utACK.

  31. theuni commented at 7:01 PM on October 2, 2014: member

    utACK.

    Sidenote: the mix of RAII/non-RAII in CAutoFile is really scary. Lots of outside functions rely on them decaying to FILE* (see FileCommit for a nasty example). That violates the principle of least surprise in a big way, imo.

    Would there be much objection to trying to reign that in by slowly extending CAutoFile (or something new) to be more full-featured, and slowly eliminating bare FILE pointers? In the example above, I can't imagine why that shouldn't be foo.commit(). I'm not aware of many other big projects that allow non-abstracted low-level structures like that.

  32. laanwj commented at 7:20 PM on October 2, 2014: member

    @theuni In principle I agree, but let's not spend too much time here unless there are concrete problems. I suppose we could pretty easily convert it to more C++ish ifstream/ofstream which is RAII by default (instead of inventing Yet Another File Wrapper which a new contributor has to learn). But on the other hand I'm afraid fiddling too much with this code will risk breaking things with no clear gain, and there are tons of actual issues to be fixed.

    Edit: BTW, maybe we should look into moving these out of serialize.h? I'd say that the serialization should be decoupled platform functionality such as files.

  33. laanwj merged this on Oct 2, 2014
  34. laanwj closed this on Oct 2, 2014

  35. laanwj referenced this in commit 0e64566a82 on Oct 2, 2014
  36. Diapolo commented at 12:17 PM on October 3, 2014: none

    @theuni @laanwj I have a working CAutoFile implementation based on std::fstream in my local build. Remeber, I tried to get this changed once and am willing to just create a new pull at any time :).

  37. Diapolo deleted the branch on Oct 3, 2014
  38. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-18 18:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me