Skip to content

Commit

Permalink
[Support/LockFileManager] Re-apply r203137 and r203138 but use symbol…
Browse files Browse the repository at this point in the history
…ic 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
  • Loading branch information
akyrtzi committed Mar 6, 2014
1 parent 4eb048a commit 046c8e1
Showing 1 changed file with 56 additions and 24 deletions.
80 changes: 56 additions & 24 deletions lib/Support/LockFileManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 046c8e1

Please sign in to comment.