[PATCH] D39710: Simplify unlinkAsync

Rafael Ávila de Espíndola via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 6 18:12:49 PST 2017


rafael created this revision.
Herald added subscribers: arichardson, emaste.

I started to take a look at our use of temporary files, with the eventual goal of never leaving a temporary file in case of crash.

The first thing I am looking at is where we use the version of createUniqueFile that doesn't open the file.  In general that can race.  In lld I think there is only one use and it is simple to avoid.

It is used to create a temp name to pass to rename, but there are simpler ways of keeping a reference to a file than renaming it.  In fact, just opening the file will do it.

I tested that the close is indeed where the time is spent by wrapping both in std::chrono::system_clock::now. The remove timed at about 5.065000e-06 seconds, the close at 3.852581e-01 seconds.


https://reviews.llvm.org/D39710

Files:
  ELF/Filesystem.cpp


Index: ELF/Filesystem.cpp
===================================================================
--- ELF/Filesystem.cpp
+++ ELF/Filesystem.cpp
@@ -16,6 +16,7 @@
 #include "lld/Common/Threads.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/FileSystem.h"
+#include <unistd.h>
 
 using namespace llvm;
 
@@ -35,27 +36,25 @@
 // Since LLD can link a 1 GB binary in about 5 seconds, that waste
 // actually counts.
 //
-// This function spawns a background thread to call unlink.
+// This function spawns a background thread to remove the file.
 // The calling thread returns almost immediately.
 void elf::unlinkAsync(StringRef Path) {
   if (!ThreadsEnabled || !sys::fs::exists(Path) ||
       !sys::fs::is_regular_file(Path))
     return;
 
-  // First, rename Path to avoid race condition. We cannot remove
-  // Path from a different thread because we are now going to create
-  // Path as a new file. If we do that in a different thread, the new
-  // thread can remove the new file.
-  SmallString<128> TempPath;
-  if (sys::fs::createUniqueFile(Path + "tmp%%%%%%%%", TempPath))
+  // We cannot just remove path from a different thread because we are now going
+  // to create path as a new file.
+  // Instead we open the file and unlink it on this thread. The unlink is fast
+  // since the open fd guarantees that it is not removing the last reference.
+  int FD;
+  if (std::error_code EC = sys::fs::openFileForRead(Path, FD))
     return;
-  if (sys::fs::rename(Path, TempPath)) {
-    sys::fs::remove(TempPath);
-    return;
-  }
 
-  // Remove TempPath in background.
-  runBackground([=] { ::remove(TempPath.str().str().c_str()); });
+  sys::fs::remove(Path);
+
+  // close and therefore remove TempPath in background.
+  runBackground([=] { ::close(FD); });
 }
 
 // Simulate file creation to see if Path is writable.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D39710.121828.patch
Type: text/x-patch
Size: 1849 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171107/f23e6e3e/attachment.bin>


More information about the llvm-commits mailing list