diff options
Diffstat (limited to 'drivers/windows')
-rw-r--r-- | drivers/windows/file_access_windows.cpp | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index dbffac8ebd..832d75b17d 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -31,6 +31,7 @@ #ifdef WINDOWS_ENABLED #include "file_access_windows.h" +#include "os/os.h" #include "shlwapi.h" #include <windows.h> @@ -115,25 +116,35 @@ void FileAccessWindows::close() { //_wunlink(save_path.c_str()); //unlink if exists //int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str()); - bool rename_error; + bool rename_error = true; + int attempts = 4; + while (rename_error && attempts) { + // This workaround of trying multiple times is added to deal with paranoid Windows + // antiviruses that love reading just written files even if they are not executable, thus + // locking the file and preventing renaming from happening. #ifdef UWP_ENABLED - // UWP has no PathFileExists, so we check attributes instead - DWORD fileAttr; + // UWP has no PathFileExists, so we check attributes instead + DWORD fileAttr; - fileAttr = GetFileAttributesW(save_path.c_str()); - if (INVALID_FILE_ATTRIBUTES == fileAttr) { + fileAttr = GetFileAttributesW(save_path.c_str()); + if (INVALID_FILE_ATTRIBUTES == fileAttr) { #else - if (!PathFileExistsW(save_path.c_str())) { + if (!PathFileExistsW(save_path.c_str())) { #endif - //creating new file - rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0; - } else { - //atomic replace for existing file - rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), NULL, 2 | 4, NULL, NULL); - } - if (rename_error && close_fail_notify) { - close_fail_notify(save_path); + //creating new file + rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0; + } else { + //atomic replace for existing file + rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), NULL, 2 | 4, NULL, NULL); + } + if (rename_error && close_fail_notify) { + close_fail_notify(save_path); + } + if (rename_error) { + attempts--; + OS::get_singleton()->delay_usec(1000000); //wait 100msec and try again + } } save_path = ""; |