diff --git a/aegisub/libaegisub/common/io.cpp b/aegisub/libaegisub/common/io.cpp index db5728dafbd95b2c386e0323ab4b62f7216bf18e..2baac82c0086c6f9e9bffc9f2c7e26c6e39e0a4c 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 6025226172c305877b40656c3bcde6378b1d3f41..26dd2970dbe1545793209da017eee6eb91a4f535 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 65c4a7c3a71dfca0e6d789bc4f2a8f50e5b65057..c7d62701f4b9d3e756b49bf2c50cbf5af5549061 100644 --- a/aegisub/libaegisub/unix/util.cpp +++ b/aegisub/libaegisub/unix/util.cpp @@ -20,6 +20,8 @@ #include "libaegisub/util.h" +#include <boost/thread.hpp> + 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 07283bd7f044a00a1fe97672599630a9571f3890..dbac2819d13a06a9cab6ea5892ce5b654aeb66bc 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 <thread> + #define WIN32_LEAN_AND_MEAN #include <windows.h> @@ -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 8f9922f5820663d00162005835ed6ebae2f66d53..700b4004dd68663c1766dc05b9c982794e2423a4 100644 --- a/aegisub/src/subtitles_provider_libass.cpp +++ b/aegisub/src/subtitles_provider_libass.cpp @@ -50,13 +50,12 @@ #include <libaegisub/dispatch.h> #include <libaegisub/log.h> +#include <libaegisub/util.h> #include <boost/gil/gil_all.hpp> #include <boost/range/algorithm_ext/push_back.hpp> -#include <boost/thread.hpp> #include <memory> #include <mutex> -#include <thread> namespace { std::unique_ptr<agi::dispatch::Queue> 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;