From: Argyrios Kyrtzidis Date: Thu, 6 Mar 2014 20:53:58 +0000 (+0000) Subject: [Support/LockFileManager] Re-apply r203137 and r203138 but use symbolic links only... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=046c8e1a3a15c9875e506e6329bf163d260134ed;p=oota-llvm.git [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203162 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp index 61afb79fb22..b45fcbca2e2 100644 --- a/lib/Support/LockFileManager.cpp +++ b/lib/Support/LockFileManager.cpp @@ -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 {