1
0
Fork 0

Remove exception in destructor of agi::io::Save

Provide Close() for error handling
Correctly parse boost error code
Handle failure in TextFileWriter

Fix wangqr/Aegisub#25
This commit is contained in:
wangqr 2019-10-17 03:13:55 -04:00
parent b2be79366e
commit f92abc863e
4 changed files with 43 additions and 3 deletions

View File

@ -30,6 +30,26 @@ namespace ec = boost::system::errc;
// boost::filesystem functions throw a single exception type for all
// errors, which isn't really what we want, so do some crazy wrapper
// shit to map error codes to more useful exceptions.
#ifdef BOOST_WINDOWS_API
#define CHECKED_CALL(exp, src_path, dst_path) \
boost::system::error_code ec; \
exp; \
switch (ec.value()) {\
case ERROR_SUCCESS: break; \
case ERROR_FILE_NOT_FOUND: throw FileNotFound(src_path); \
case ERROR_DIRECTORY: throw NotADirectory(src_path); \
case ERROR_DISK_FULL: throw DriveFull(dst_path); \
case ERROR_ACCESS_DENIED: \
if (!src_path.empty()) \
acs::CheckFileRead(src_path); \
if (!dst_path.empty()) \
acs::CheckFileWrite(dst_path); \
throw AccessDenied(src_path); \
default: \
LOG_D("filesystem") << "Unknown error when calling '" << #exp << "': " << ec << ": " << ec.message(); \
throw FileSystemUnknownError(ec.message()); \
}
#else
#define CHECKED_CALL(exp, src_path, dst_path) \
boost::system::error_code ec; \
exp; \
@ -49,6 +69,7 @@ namespace ec = boost::system::errc;
LOG_D("filesystem") << "Unknown error when calling '" << #exp << "': " << ec << ": " << ec.message(); \
throw FileSystemUnknownError(ec.message()); \
}
#endif
#define CHECKED_CALL_RETURN(exp, src_path) \
CHECKED_CALL(auto ret = exp, src_path, agi::fs::path()); \

View File

@ -56,7 +56,8 @@ Save::Save(fs::path const& file, bool binary)
}
}
Save::~Save() noexcept(false) {
void Save::Close() {
if (!fp) return;
fp.reset(); // Need to close before rename on Windows to unlock the file
for (int i = 0; i < 10; ++i) {
try {
@ -72,5 +73,12 @@ Save::~Save() noexcept(false) {
}
}
Save::~Save() {
try {
Close();
}
catch (agi::fs::FileSystemError const&) {}
}
} // namespace io
} // namespace agi

View File

@ -38,8 +38,9 @@ class Save {
public:
Save(fs::path const& file, bool binary = false);
~Save() noexcept(false);
~Save();
std::ostream& Get() { return *fp; }
void Close();
};
} // namespace io

View File

@ -24,6 +24,7 @@
#include "options.h"
#include <libaegisub/io.h>
#include <libaegisub/fs.h>
#include <libaegisub/charset_conv.h>
#include <libaegisub/make_unique.h>
@ -49,7 +50,16 @@ TextFileWriter::TextFileWriter(agi::fs::path const& filename, std::string encodi
}
TextFileWriter::~TextFileWriter() {
// Explicit empty destructor required with a unique_ptr to an incomplete class
try {
file->Close();
}
catch (agi::fs::FileSystemError const&e) {
wxString m = wxString::FromUTF8(e.GetMessage());
if (!m.empty())
wxMessageBox(m, "Exception in agi::io::Save", wxOK | wxCENTRE | wxICON_ERROR);
else
wxMessageBox(e.GetMessage(), "Exception in agi::io::Save", wxOK | wxCENTRE | wxICON_ERROR);
}
}
void TextFileWriter::WriteLineToFile(std::string const& line, bool addLineBreak) {