diff options
author | Sunil Srivastava <sunil_srivastava@playstation.sony.com> | 2016-03-25 23:41:28 +0000 |
---|---|---|
committer | Sunil Srivastava <sunil_srivastava@playstation.sony.com> | 2016-03-25 23:41:28 +0000 |
commit | 34fce9377ed64f679f3912d0e8a20cabb5d1e978 (patch) | |
tree | f14e05b396c92d59f961faefd6717431653f0c4b /llvm/lib/Support/Windows/Path.inc | |
parent | 65fd8f4345e841bcbe68c53b2f808eb53e4bf24e (diff) | |
download | bcm5719-llvm-34fce9377ed64f679f3912d0e8a20cabb5d1e978.tar.gz bcm5719-llvm-34fce9377ed64f679f3912d0e8a20cabb5d1e978.zip |
Improve the reliability of file renaming in Windows by having the compiler retry
the rename operation on 3 error conditions of ReplaceFileW() that it was
previously bailing out on.
Patch by Douglas Yung!
Differential Revision: http://reviews.llvm.org/D17903
llvm-svn: 264477
Diffstat (limited to 'llvm/lib/Support/Windows/Path.inc')
-rw-r--r-- | llvm/lib/Support/Windows/Path.inc | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index 24f2fa531c5..98fd7b0034a 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -265,24 +265,43 @@ std::error_code rename(const Twine &from, const Twine &to) { std::error_code ec = std::error_code(); - // Retry while we see ERROR_ACCESS_DENIED. + // Retry while we see recoverable errors. // System scanners (eg. indexer) might open the source file when it is written // and closed. - for (int i = 0; i < 2000; i++) { - // Try ReplaceFile first, as it is able to associate a new data stream with - // the destination even if the destination file is currently open. - if (::ReplaceFileW(wide_to.begin(), wide_from.begin(), NULL, 0, NULL, NULL)) - return std::error_code(); + bool TryReplace = true; - // We get ERROR_FILE_NOT_FOUND if the destination file is missing. - // MoveFileEx can handle this case. - DWORD ReplaceError = ::GetLastError(); - ec = mapWindowsError(ReplaceError); - if (ReplaceError != ERROR_ACCESS_DENIED && - ReplaceError != ERROR_FILE_NOT_FOUND && - ReplaceError != ERROR_SHARING_VIOLATION) - break; + for (int i = 0; i < 2000; i++) { + if (i > 0) + ::Sleep(1); + + if (TryReplace) { + // Try ReplaceFile first, as it is able to associate a new data stream + // with the destination even if the destination file is currently open. + if (::ReplaceFileW(wide_to.data(), wide_from.data(), NULL, 0, NULL, NULL)) + return std::error_code(); + + DWORD ReplaceError = ::GetLastError(); + ec = mapWindowsError(ReplaceError); + + // If ReplaceFileW returned ERROR_UNABLE_TO_MOVE_REPLACEMENT or + // ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, retry but only use MoveFileExW(). + if (ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT || + ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2) { + TryReplace = false; + continue; + } + // If ReplaceFileW returned ERROR_UNABLE_TO_REMOVE_REPLACED, retry + // using ReplaceFileW(). + if (ReplaceError == ERROR_UNABLE_TO_REMOVE_REPLACED) + continue; + // We get ERROR_FILE_NOT_FOUND if the destination file is missing. + // MoveFileEx can handle this case. + if (ReplaceError != ERROR_ACCESS_DENIED && + ReplaceError != ERROR_FILE_NOT_FOUND && + ReplaceError != ERROR_SHARING_VIOLATION) + break; + } if (::MoveFileExW(wide_from.begin(), wide_to.begin(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) @@ -291,8 +310,6 @@ std::error_code rename(const Twine &from, const Twine &to) { DWORD MoveError = ::GetLastError(); ec = mapWindowsError(MoveError); if (MoveError != ERROR_ACCESS_DENIED) break; - - ::Sleep(1); } return ec; |