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 the- AutoFile::write()method) and hope that- fclose(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 AutoFileso 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 AutoFileconstructor 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 theAutoFileobject 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()).