diff --git a/aegisub/libaegisub/common/io.cpp b/aegisub/libaegisub/common/io.cpp index db5728daf..2baac82c0 100644 --- a/aegisub/libaegisub/common/io.cpp +++ b/aegisub/libaegisub/common/io.cpp @@ -64,7 +64,18 @@ Save::Save(fs::path const& file, bool binary) Save::~Save() { fp->close(); // Need to close before rename on Windows to unlock the file - fs::Rename(tmp_name, file_name); + for (int i = 0; i < 10; ++i) { + try { + fs::Rename(tmp_name, file_name); + return; + } + catch (agi::fs::FileSystemError const&) { + // Retry up to ten times in case it's just locked by a poorly-written antivirus scanner + if (i == 9) + throw; + util::sleep_for(100); + } + } } } // namespace io diff --git a/aegisub/libaegisub/include/libaegisub/util.h b/aegisub/libaegisub/include/libaegisub/util.h index 602522617..26dd2970d 100644 --- a/aegisub/libaegisub/include/libaegisub/util.h +++ b/aegisub/libaegisub/include/libaegisub/util.h @@ -70,5 +70,10 @@ namespace agi { } #endif + /// A thin wrapper around this_thread::sleep_for that uses std::thread on + /// Windows (to avoid having to compile boost.thread) and boost::thread + /// elsewhere (because libstcc++ 4.7 is missing it). + void sleep_for(int ms); + } // namespace util } // namespace agi diff --git a/aegisub/libaegisub/unix/util.cpp b/aegisub/libaegisub/unix/util.cpp index 65c4a7c3a..c7d62701f 100644 --- a/aegisub/libaegisub/unix/util.cpp +++ b/aegisub/libaegisub/unix/util.cpp @@ -20,6 +20,8 @@ #include "libaegisub/util.h" +#include + namespace agi { namespace util { timeval time_log() { @@ -30,4 +32,8 @@ timeval time_log() { void SetThreadName(const char *) { } +void sleep_for(int ms) { + boost::this_thread::sleep_for(boost::chrono::milliseconds(ms)); +} + } } diff --git a/aegisub/libaegisub/windows/util_win.cpp b/aegisub/libaegisub/windows/util_win.cpp index 07283bd7f..dbac2819d 100644 --- a/aegisub/libaegisub/windows/util_win.cpp +++ b/aegisub/libaegisub/windows/util_win.cpp @@ -23,6 +23,8 @@ #include "libaegisub/charset_conv_win.h" +#include + #define WIN32_LEAN_AND_MEAN #include @@ -99,5 +101,9 @@ void SetThreadName(LPCSTR szThreadName) { __except (EXCEPTION_CONTINUE_EXECUTION) {} } +void sleep_for(int ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +} + } // namespace io } // namespace agi diff --git a/aegisub/src/subtitles_provider_libass.cpp b/aegisub/src/subtitles_provider_libass.cpp index 8f9922f58..700b4004d 100644 --- a/aegisub/src/subtitles_provider_libass.cpp +++ b/aegisub/src/subtitles_provider_libass.cpp @@ -50,13 +50,12 @@ #include #include +#include #include #include -#include #include #include -#include namespace { std::unique_ptr cache_queue; @@ -104,11 +103,7 @@ LibassSubtitlesProvider::LibassSubtitlesProvider(std::string) progress.Run([=](agi::ProgressSink *ps) { ps->SetIndeterminate(); while (!*done && !ps->IsCancelled()) -#ifdef _MSC_VER - std::this_thread::sleep_for(std::chrono::milliseconds(250)); -#else - boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); -#endif + agi::util::sleep_for(250); }); ass_renderer = *renderer;