From a17bd121850a7e1c57cd0bd9d7553b35a72f0c39 Mon Sep 17 00:00:00 2001 From: Bob Haarman Date: Fri, 10 Nov 2017 17:08:21 +0000 Subject: [PATCH] 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 llvm-svn: 317899 --- llvm/lib/LTO/Caching.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/llvm/lib/LTO/Caching.cpp b/llvm/lib/LTO/Caching.cpp index 1708ab4..32fdd42 100644 --- a/llvm/lib/LTO/Caching.cpp +++ b/llvm/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 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); } -- 2.7.4