[llvm] r203162 - [Support/LockFileManager] Re-apply r203137 and r203138 but use symbolic links only on unix.

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Mar 6 12:53:58 PST 2014


Author: akirtzidis
Date: Thu Mar  6 14:53:58 2014
New Revision: 203162

URL: http://llvm.org/viewvc/llvm-project?rev=203162&view=rev
Log:
[Support/LockFileManager] Re-apply r203137 and r203138 but use symbolic links only on unix.

Reid Kleckner pointed out that we can't use symbolic links on Windows.

Modified:
    llvm/trunk/lib/Support/LockFileManager.cpp

Modified: llvm/trunk/lib/Support/LockFileManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/LockFileManager.cpp?rev=203162&r1=203161&r2=203162&view=diff
==============================================================================
--- llvm/trunk/lib/Support/LockFileManager.cpp (original)
+++ llvm/trunk/lib/Support/LockFileManager.cpp Thu Mar  6 14:53:58 2014
@@ -67,6 +67,22 @@ bool LockFileManager::processStillExecut
   return true;
 }
 
+#if LLVM_ON_UNIX
+static error_code unix_create_symbolic_link(const Twine &to,
+                                            const Twine &from) {
+  // Get arguments.
+  SmallString<128> from_storage;
+  SmallString<128> to_storage;
+  StringRef f = from.toNullTerminatedStringRef(from_storage);
+  StringRef t = to.toNullTerminatedStringRef(to_storage);
+
+  if (::symlink(t.begin(), f.begin()) == -1)
+    return error_code(errno, system_category());
+
+  return error_code::success();
+}
+#endif
+
 LockFileManager::LockFileManager(StringRef FileName)
 {
   this->FileName = FileName;
@@ -115,34 +131,50 @@ LockFileManager::LockFileManager(StringR
     }
   }
 
-  // Create a hard link from the lock file name. If this succeeds, we're done.
-  error_code EC
-    = sys::fs::create_hard_link(UniqueLockFileName.str(),
-                                      LockFileName.str());
-  if (EC == errc::success)
-    return;
+  while (1) {
+#if LLVM_ON_UNIX
+    // Create a symbolic link from the lock file name. If this succeeds, we're
+    // done. Note that we are using symbolic link because hard links are not
+    // supported by all filesystems.
+    error_code EC
+      = unix_create_symbolic_link(UniqueLockFileName.str(),
+                                        LockFileName.str());
+#else
+    // We can't use symbolic links for windows.
+    // Create a hard link from the lock file name. If this succeeds, we're done.
+    error_code EC
+      = sys::fs::create_hard_link(UniqueLockFileName.str(),
+                                        LockFileName.str());
+#endif
+    if (EC == errc::success)
+      return;
 
-  // Creating the hard link failed.
+    if (EC != errc::file_exists) {
+      Error = EC;
+      return;
+    }
 
-#ifdef LLVM_ON_UNIX
-  // The creation of the hard link may appear to fail, but if stat'ing the
-  // unique file returns a link count of 2, then we can still declare success.
-  struct stat StatBuf;
-  if (stat(UniqueLockFileName.c_str(), &StatBuf) == 0 &&
-      StatBuf.st_nlink == 2)
-    return;
-#endif
+    // Someone else managed to create the lock file first. Read the process ID
+    // from the lock file.
+    if ((Owner = readLockFile(LockFileName))) {
+      // Wipe out our unique lock file (it's useless now)
+      sys::fs::remove(UniqueLockFileName.str());
+      return;
+    }
 
-  // Someone else managed to create the lock file first. Wipe out our unique
-  // lock file (it's useless now) and read the process ID from the lock file.
-  sys::fs::remove(UniqueLockFileName.str());
-  if ((Owner = readLockFile(LockFileName)))
-    return;
+    if (!sys::fs::exists(LockFileName.str())) {
+      // The previous owner released the lock file before we could read it.
+      // Try to get ownership again.
+      continue;
+    }
 
-  // There is a lock file that nobody owns; try to clean it up and report
-  // an error.
-  sys::fs::remove(LockFileName.str());
-  Error = EC;
+    // There is a lock file that nobody owns; try to clean it up and get
+    // ownership.
+    if ((EC = sys::fs::remove(LockFileName.str()))) {
+      Error = EC;
+      return;
+    }
+  }
 }
 
 LockFileManager::LockFileState LockFileManager::getState() const {





More information about the llvm-commits mailing list