- 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
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-
Diapolo commented at 6:57 AM on September 25, 2014: none
-
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.
-
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.
- Diapolo renamed this:
add missing fclose on exception in LoadExternalBlockFile()
convert CBufferedFile into a RAII wrapper
on Sep 25, 2014 -
laanwj commented at 12:11 PM on September 25, 2014: member
Looks good to me now.
-
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(...) -
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
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.
Diapolo renamed this:convert CBufferedFile into a RAII wrapper
convert CBufferedFile into a non-refcounted RAII wrapper
on Sep 28, 2014Diapolo commented at 1:41 PM on September 28, 2014: noneUpdated to include:
- update CAutoFile destructor to match CBufferdFile destructor
- CBufferedFile: make src protected, nType and nVersion private
- CAutoFile: make nType and nVersion private
laanwj commented at 12:59 PM on September 29, 2014: memberThat's a lot of red...
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.
laanwj commented at 1:24 PM on September 29, 2014: memberWell 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.
Diapolo commented at 2:12 PM on September 29, 2014: noneNow 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.BitcoinPullTester commented at 7:33 PM on September 29, 2014: noneAutomatic 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:
- 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)
- It adds/modifies tests which test network rules (thanks for doing that), which conflicts with a patch applied at test time
- It does not build on either Linux i386 or Win32 (via MinGW cross compile)
- The test suite fails on either Linux i386 or Win32
- 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.
theuni commented at 12:19 AM on October 2, 2014: memberWhy 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.
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.
c9fb27da0aCBufferedFile: 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
0c35486dc9CBufferedFile: add explicit close function
- also use identical close function for CAutoFile (avoids setting file to NULL under wrong conditions)
CAutoFile: make file private 938bccebf1Diapolo renamed this:convert CBufferedFile into a non-refcounted RAII wrapper
CBufferedFile: convert into a non-refcounted RAII wrapper
on Oct 2, 2014laanwj commented at 9:53 AM on October 2, 2014: memberLooks good to me now. utACK.
theuni commented at 7:01 PM on October 2, 2014: memberutACK.
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.
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.
laanwj merged this on Oct 2, 2014laanwj closed this on Oct 2, 2014laanwj referenced this in commit 0e64566a82 on Oct 2, 2014Diapolo deleted the branch on Oct 3, 2014MarcoFalke locked this on Sep 8, 2021Contributors
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
More mirrored repositories can be found on mirror.b10c.me