summaryrefslogtreecommitdiff
path: root/lib/LTO
diff options
context:
space:
mode:
authorBob Haarman <llvm@inglorion.net>2017-11-10 17:08:21 +0000
committerBob Haarman <llvm@inglorion.net>2017-11-10 17:08:21 +0000
commitd4f1cfbb84de69a56f1fe854cfe142a844754e70 (patch)
tree3c40115ea303b541faf816538dfa379d900afd92 /lib/LTO
parentdc7bbb86a47a53898096fa1e9da5b9f1ee20b2fc (diff)
LTO: don't fatal when value for cache key already exists
Summary: LTO/Caching.cpp uses file rename to atomically set the value for a cache key. On Windows, this fails when the destination file already exists. Previously, LLVM would report_fatal_error in such cases. However, because the old and the new value for the cache key are supposed to be equivalent, it actually doesn't matter which one we keep. This change makes it so that failing the rename when an openable file with the desired name already exists causes us to report success instead of fataling. Reviewers: pcc, hans Subscribers: mehdi_amini, llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D39874 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317899 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/LTO')
-rw-r--r--lib/LTO/Caching.cpp17
1 files changed, 15 insertions, 2 deletions
diff --git a/lib/LTO/Caching.cpp b/lib/LTO/Caching.cpp
index 1708ab4c5c7..32fdd422187 100644
--- a/lib/LTO/Caching.cpp
+++ b/lib/LTO/Caching.cpp
@@ -14,9 +14,9 @@
#include "llvm/LTO/Caching.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -72,10 +72,23 @@ Expected<NativeObjectCache> lto::localCache(StringRef CacheDirectoryPath,
MBOrErr.getError().message() + "\n");
// This is atomic on POSIX systems.
- if (auto EC = sys::fs::rename(TempFilename, EntryPath))
+ // On Windows, it can fail with permission denied if the destination
+ // file already exists. Since the existing file should be semantically
+ // equivalent to the one we are trying to write, we give AddBuffer
+ // a copy of the bytes we wrote in that case. We do this instead of
+ // just using the existing file, because the pruner might delete the
+ // file before we get a chance to use it.
+ auto EC = sys::fs::rename(TempFilename, EntryPath);
+ if (EC == errc::permission_denied) {
+ auto MBCopy = MemoryBuffer::getMemBufferCopy(
+ (*MBOrErr)->getBuffer(), EntryPath);
+ MBOrErr = std::move(MBCopy);
+ sys::fs::remove(TempFilename);
+ } else if (EC) {
report_fatal_error(Twine("Failed to rename temporary file ") +
TempFilename + " to " + EntryPath + ": " +
EC.message() + "\n");
+ }
AddBuffer(Task, std::move(*MBOrErr), EntryPath);
}