[llvm] r318322 - Use TempFile in lto caching.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 15 11:09:23 PST 2017


Author: rafael
Date: Wed Nov 15 11:09:22 2017
New Revision: 318322

URL: http://llvm.org/viewvc/llvm-project?rev=318322&view=rev
Log:
Use TempFile in lto caching.

This requires a small change to TempFile: allowing a discard after a
failed keep.

With this the cache now handles signals and reuses a fd instead of
reopening the file.

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

Modified: llvm/trunk/lib/LTO/Caching.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/Caching.cpp?rev=318322&r1=318321&r2=318322&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/Caching.cpp (original)
+++ llvm/trunk/lib/LTO/Caching.cpp Wed Nov 15 11:09:22 2017
@@ -48,27 +48,29 @@ Expected<NativeObjectCache> lto::localCa
     // file to the cache and calling AddBuffer to add it to the link.
     struct CacheStream : NativeObjectStream {
       AddBufferFn AddBuffer;
-      std::string TempFilename;
+      sys::fs::TempFile TempFile;
       std::string EntryPath;
       unsigned Task;
 
       CacheStream(std::unique_ptr<raw_pwrite_stream> OS, AddBufferFn AddBuffer,
-                  std::string TempFilename, std::string EntryPath,
+                  sys::fs::TempFile TempFile, std::string EntryPath,
                   unsigned Task)
           : NativeObjectStream(std::move(OS)), AddBuffer(std::move(AddBuffer)),
-            TempFilename(std::move(TempFilename)),
-            EntryPath(std::move(EntryPath)), Task(Task) {}
+            TempFile(std::move(TempFile)), EntryPath(std::move(EntryPath)),
+            Task(Task) {}
 
       ~CacheStream() {
-        // Make sure the file is closed before committing it.
+        // Make sure the stream is closed before committing it.
         OS.reset();
 
         // Open the file first to avoid racing with a cache pruner.
         ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
-            MemoryBuffer::getFile(TempFilename);
+            MemoryBuffer::getOpenFile(TempFile.FD, TempFile.TmpName,
+                                      /*FileSize*/ -1,
+                                      /*RequiresNullTerminator*/ false);
         if (!MBOrErr)
           report_fatal_error(Twine("Failed to open new cache file ") +
-                             TempFilename + ": " +
+                             TempFile.TmpName + ": " +
                              MBOrErr.getError().message() + "\n");
 
         // This is atomic on POSIX systems.
@@ -78,17 +80,26 @@ Expected<NativeObjectCache> lto::localCa
         // 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);
+        Error E = TempFile.keep(EntryPath);
+        E = handleErrors(std::move(E), [&](const ECError &E) -> Error {
+          std::error_code EC = E.convertToErrorCode();
+          if (EC != errc::permission_denied)
+            return errorCodeToError(EC);
+
+          auto MBCopy = MemoryBuffer::getMemBufferCopy((*MBOrErr)->getBuffer(),
+                                                       EntryPath);
           MBOrErr = std::move(MBCopy);
-          sys::fs::remove(TempFilename);
-        } else if (EC) {
+
+          // FIXME: should we consume the discard error?
+          consumeError(TempFile.discard());
+
+          return Error::success();
+        });
+
+        if (E)
           report_fatal_error(Twine("Failed to rename temporary file ") +
-                             TempFilename + " to " + EntryPath + ": " +
-                             EC.message() + "\n");
-        }
+                             TempFile.TmpName + " to " + EntryPath + ": " +
+                             toString(std::move(E)) + "\n");
 
         AddBuffer(Task, std::move(*MBOrErr), EntryPath);
       }
@@ -96,21 +107,19 @@ Expected<NativeObjectCache> lto::localCa
 
     return [=](size_t Task) -> std::unique_ptr<NativeObjectStream> {
       // Write to a temporary to avoid race condition
-      int TempFD;
-      SmallString<64> TempFilenameModel, TempFilename;
+      SmallString<64> TempFilenameModel;
       sys::path::append(TempFilenameModel, CacheDirectoryPath, "Thin-%%%%%%.tmp.o");
-      std::error_code EC =
-          sys::fs::createUniqueFile(TempFilenameModel, TempFD, TempFilename,
-                                    sys::fs::owner_read | sys::fs::owner_write);
-      if (EC) {
-        errs() << "Error: " << EC.message() << "\n";
+      Expected<sys::fs::TempFile> Temp = sys::fs::TempFile::create(
+          TempFilenameModel, sys::fs::owner_read | sys::fs::owner_write);
+      if (!Temp) {
+        errs() << "Error: " << toString(Temp.takeError()) << "\n";
         report_fatal_error("ThinLTO: Can't get a temporary file");
       }
 
       // This CacheStream will move the temporary file into the cache when done.
       return llvm::make_unique<CacheStream>(
-          llvm::make_unique<raw_fd_ostream>(TempFD, /* ShouldClose */ true),
-          AddBuffer, TempFilename.str(), EntryPath.str(), Task);
+          llvm::make_unique<raw_fd_ostream>(Temp->FD, /* ShouldClose */ false),
+          AddBuffer, std::move(*Temp), EntryPath.str(), Task);
     };
   };
 }

Modified: llvm/trunk/lib/Support/Path.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Path.cpp?rev=318322&r1=318321&r2=318322&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Path.cpp (original)
+++ llvm/trunk/lib/Support/Path.cpp Wed Nov 15 11:09:22 2017
@@ -772,13 +772,14 @@ TempFile &TempFile::operator=(TempFile &
 TempFile::~TempFile() { assert(Done); }
 
 Error TempFile::discard() {
-  if (Done)
-    return Error::success();
   Done = true;
   // Always try to close and remove.
-  std::error_code RemoveEC = fs::remove(TmpName);
-  sys::DontRemoveFileOnSignal(TmpName);
-  if (close(FD) == -1) {
+  std::error_code RemoveEC;
+  if (!TmpName.empty()) {
+    RemoveEC = fs::remove(TmpName);
+    sys::DontRemoveFileOnSignal(TmpName);
+  }
+  if (FD != -1 && close(FD) == -1) {
     std::error_code EC = std::error_code(errno, std::generic_category());
     return errorCodeToError(EC);
   }
@@ -791,10 +792,16 @@ Error TempFile::keep(const Twine &Name)
   // Always try to close and rename.
   std::error_code RenameEC = fs::rename(TmpName, Name);
   sys::DontRemoveFileOnSignal(TmpName);
+
+  if (!RenameEC)
+    TmpName = "";
+
   if (close(FD) == -1) {
     std::error_code EC(errno, std::generic_category());
     return errorCodeToError(EC);
   }
+  FD = -1;
+
   return errorCodeToError(RenameEC);
 }
 




More information about the llvm-commits mailing list