[Support/LockFileManager] Re-apply r203137 and r203138 but use symbolic links only...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 6 Mar 2014 20:53:58 +0000 (20:53 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 6 Mar 2014 20:53:58 +0000 (20:53 +0000)
Reid Kleckner pointed out that we can't use symbolic links on Windows.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203162 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/LockFileManager.cpp

index 61afb79fb2278377793b0f3e42919cacb84f76f1..b45fcbca2e23e4466884bdae67f9ef3f2b72e5ab 100644 (file)
@@ -67,6 +67,22 @@ bool LockFileManager::processStillExecuting(StringRef Hostname, int PID) {
   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(StringRef FileName)
     }
   }
 
-  // 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 {