Attempt renaming multiple times on safe file save, and make the behavior optional. Fixes #14339.

This commit is contained in:
Juan Linietsky 2018-01-12 17:03:08 -03:00
parent d486cae701
commit e56b3439a5
2 changed files with 26 additions and 15 deletions

View file

@ -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 = "";

View file

@ -4749,7 +4749,7 @@ EditorNode::EditorNode() {
scene_distraction = false;
script_distraction = false;
FileAccess::set_backup_save(true);
FileAccess::set_backup_save(EDITOR_DEF("filesystem/on_save/safe_save_on_backup_then_rename", true));
TranslationServer::get_singleton()->set_enabled(false);
// load settings