[llvm] r317899 - LTO: don't fatal when value for cache key already exists

Bob Haarman via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 10 09:08:21 PST 2017


Author: inglorion
Date: Fri Nov 10 09:08:21 2017
New Revision: 317899

URL: http://llvm.org/viewvc/llvm-project?rev=317899&view=rev
Log:
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

Modified:
    llvm/trunk/lib/LTO/Caching.cpp

Modified: llvm/trunk/lib/LTO/Caching.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/Caching.cpp?rev=317899&r1=317898&r2=317899&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/Caching.cpp (original)
+++ llvm/trunk/lib/LTO/Caching.cpp Fri Nov 10 09:08:21 2017
@@ -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::localCa
                              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);
       }




More information about the llvm-commits mailing list