mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-04 18:22:57 +02:00
Merge bitcoin/bitcoin#29307: util: explicitly close all AutoFiles that have been written
c10e382d2aflatfile: check whether the file has been closed successfully (Vasil Dimov)4bb5dd78eautil: check that a file has been closed before ~AutoFile() is called (Vasil Dimov)8bb34f07dfExplicitly close all AutoFiles that have been written (Vasil Dimov)a69c4098b2rpc: take ownership of the file by WriteUTXOSnapshot() (Hodlinator) Pull request description: `fclose(3)` may fail to flush the previously written data to disk, thus a failing `fclose(3)` is as serious as a failing `fwrite(3)`. Previously the code ignored `fclose(3)` failures. This PR improves that by changing all users of `AutoFile` that use it to write data to explicitly close the file and handle a possible error. --- Other alternatives are: 1. `fflush(3)` after each write to the file (and throw if it fails from the `AutoFile::write()` method) and hope that `fclose(3)` will then always succeed. Assert that it succeeds from the destructor 🙄. Will hurt performance. 2. Throw nevertheless from the destructor. Exception within the exception in C++ I think results in terminating the program without a useful message. 3. (this is implemented in the latest incarnation of this PR) Redesign `AutoFile` so that its destructor cannot fail. Adjust _all_ its users 😭. For example, if the file has been written to, then require the callers to explicitly call the `AutoFile::fclose()` method before the object goes out of scope. In the destructor, as a sanity check, assume/assert that this is indeed the case. Defeats the purpose of a RAII wrapper for `FILE*` which automatically closes the file when it goes out of scope and there are a lot of users of `AutoFile`. 4. Pass a new callback function to the `AutoFile` constructor which will be called from the destructor to handle `fclose()` errors, as described in https://github.com/bitcoin/bitcoin/pull/29307#issuecomment-2243842400. My thinking is that if that callback is going to only log a message, then we can log the message directly from the destructor without needing a callback. If the callback is going to do more complicated error handling then it is easier to do that at the call site by directly calling `AutoFile::fclose()` instead of getting the `AutoFile` object out of scope (so that its destructor is called) and inspecting for side effects done by the callback (e.g. set a variable to indicate a failed `fclose()`). ACKs for top commit: l0rinc: ACKc10e382d2aachow101: ACKc10e382d2ahodlinator: re-ACKc10e382d2aTree-SHA512: 3994ca57e5b2b649fc84f24dad144173b7500fc0e914e06291d5c32fbbf8d2b1f8eae0040abd7a5f16095ddf4e11fe1636c6092f49058cda34f3eb2ee536d7ba
This commit is contained in:
@@ -47,7 +47,7 @@ FUZZ_TARGET(autofile)
|
||||
}
|
||||
},
|
||||
[&] {
|
||||
auto_file.fclose();
|
||||
(void)auto_file.fclose();
|
||||
},
|
||||
[&] {
|
||||
ReadFromStream(fuzzed_data_provider, auto_file);
|
||||
@@ -62,5 +62,7 @@ FUZZ_TARGET(autofile)
|
||||
if (f != nullptr) {
|
||||
fclose(f);
|
||||
}
|
||||
} else {
|
||||
(void)auto_file.fclose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,5 +111,6 @@ FUZZ_TARGET(policy_estimator, .init = initialize_policy_estimator)
|
||||
AutoFile fuzzed_auto_file{fuzzed_file_provider.open()};
|
||||
block_policy_estimator.Write(fuzzed_auto_file);
|
||||
block_policy_estimator.Read(fuzzed_auto_file);
|
||||
(void)fuzzed_auto_file.fclose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,5 @@ FUZZ_TARGET(policy_estimator_io, .init = initialize_policy_estimator_io)
|
||||
if (block_policy_estimator.Read(fuzzed_auto_file)) {
|
||||
block_policy_estimator.Write(fuzzed_auto_file);
|
||||
}
|
||||
(void)fuzzed_auto_file.fclose();
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ void utxo_snapshot_fuzz(FuzzBufferType buffer)
|
||||
WriteCompactSize(outfile, 999); // index of coin
|
||||
outfile << Coin{coinbase->vout[0], /*nHeightIn=*/999, /*fCoinBaseIn=*/0};
|
||||
}
|
||||
assert(outfile.fclose() == 0);
|
||||
}
|
||||
|
||||
const auto ActivateFuzzedSnapshot{[&] {
|
||||
|
||||
Reference in New Issue
Block a user