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;