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:
fflush(3)
after each write to the file (and throw if it fails from theAutoFile::write()
method) and hope thatfclose(3)
will then always succeed. Assert that it succeeds from the destructor :roll_eyes:. Will hurt performance.- Throw nevertheless from the destructor. Exception within the exception in C++ I think results in terminating the program without a useful message.
- (this is implemented in the latest incarnation of this PR) Redesign
AutoFile
so that its destructor cannot fail. Adjust all its users :sob:. For example, if the file has been written to, then require the callers to explicitly call theAutoFile::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 forFILE*
which automatically closes the file when it goes out of scope and there are a lot of users ofAutoFile
. - Pass a new callback function to the
AutoFile
constructor which will be called from the destructor to handlefclose()
errors, as described in #29307 (comment). 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 callingAutoFile::fclose()
instead of getting theAutoFile
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 failedfclose()
).