diff options
Diffstat (limited to 'llvm/lib/Support/LockFileManager.cpp')
-rw-r--r-- | llvm/lib/Support/LockFileManager.cpp | 115 |
1 files changed, 45 insertions, 70 deletions
diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp index ac26646..7cf9db3 100644 --- a/llvm/lib/Support/LockFileManager.cpp +++ b/llvm/lib/Support/LockFileManager.cpp @@ -51,7 +51,7 @@ using namespace llvm; /// \param LockFileName The name of the lock file to read. /// /// \returns The process ID of the process that owns this lock file -std::optional<std::pair<std::string, int>> +std::optional<LockFileManager::OwnedByAnother> LockFileManager::readLockFile(StringRef LockFileName) { // Read the owning host and PID out of the lock file. If it appears that the // owning process is dead, the lock file is invalid. @@ -69,8 +69,10 @@ LockFileManager::readLockFile(StringRef LockFileName) { PIDStr = PIDStr.substr(PIDStr.find_first_not_of(' ')); int PID; if (!PIDStr.getAsInteger(10, PID)) { - auto Owner = std::make_pair(std::string(Hostname), PID); - if (processStillExecuting(Owner.first, Owner.second)) + OwnedByAnother Owner; + Owner.OwnerHostName = Hostname; + Owner.OwnerPID = PID; + if (processStillExecuting(Owner.OwnerHostName, Owner.OwnerPID)) return Owner; } @@ -158,41 +160,40 @@ public: } // end anonymous namespace LockFileManager::LockFileManager(StringRef FileName) -{ - this->FileName = FileName; - if (std::error_code EC = sys::fs::make_absolute(this->FileName)) { - std::string S("failed to obtain absolute path for "); - S.append(std::string(this->FileName)); - setError(EC, S); - return; - } - LockFileName = this->FileName; + : FileName(FileName), Owner(OwnerUnknown{}) {} + +Expected<bool> LockFileManager::tryLock() { + assert(std::holds_alternative<OwnerUnknown>(Owner) && + "lock has already been attempted"); + + SmallString<128> AbsoluteFileName(FileName); + if (std::error_code EC = sys::fs::make_absolute(AbsoluteFileName)) + return createStringError(EC, "failed to obtain absolute path for " + + AbsoluteFileName); + LockFileName = AbsoluteFileName; LockFileName += ".lock"; // If the lock file already exists, don't bother to try to create our own // lock file; it won't work anyway. Just figure out who owns this lock file. - if ((Owner = readLockFile(LockFileName))) - return; + if (auto LockFileOwner = readLockFile(LockFileName)) { + Owner = std::move(*LockFileOwner); + return false; + } // Create a lock file that is unique to this instance. UniqueLockFileName = LockFileName; UniqueLockFileName += "-%%%%%%%%"; int UniqueLockFileID; if (std::error_code EC = sys::fs::createUniqueFile( - UniqueLockFileName, UniqueLockFileID, UniqueLockFileName)) { - std::string S("failed to create unique file "); - S.append(std::string(UniqueLockFileName)); - setError(EC, S); - return; - } + UniqueLockFileName, UniqueLockFileID, UniqueLockFileName)) + return createStringError(EC, "failed to create unique file " + + UniqueLockFileName); // Write our process ID to our unique lock file. { SmallString<256> HostID; - if (auto EC = getHostID(HostID)) { - setError(EC, "failed to get host id"); - return; - } + if (auto EC = getHostID(HostID)) + return createStringError(EC, "failed to get host id"); raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true); Out << HostID << ' ' << sys::Process::getProcessId(); @@ -201,13 +202,12 @@ LockFileManager::LockFileManager(StringRef FileName) if (Out.has_error()) { // We failed to write out PID, so report the error, remove the // unique lock file, and fail. - std::string S("failed to write to "); - S.append(std::string(UniqueLockFileName)); - setError(Out.error(), S); + Error Err = createStringError(Out.error(), + "failed to write to " + UniqueLockFileName); sys::fs::remove(UniqueLockFileName); // Don't call report_fatal_error. Out.clear_error(); - return; + return std::move(Err); } } @@ -221,23 +221,21 @@ LockFileManager::LockFileManager(StringRef FileName) sys::fs::create_link(UniqueLockFileName, LockFileName); if (!EC) { RemoveUniqueFile.lockAcquired(); - return; + Owner = OwnedByUs{}; + return true; } - if (EC != errc::file_exists) { - std::string S("failed to create link "); - raw_string_ostream OSS(S); - OSS << LockFileName.str() << " to " << UniqueLockFileName.str(); - setError(EC, S); - return; - } + if (EC != errc::file_exists) + return createStringError(EC, "failed to create link " + LockFileName + + " to " + UniqueLockFileName); // Someone else managed to create the lock file first. Read the process ID // from the lock file. - if ((Owner = readLockFile(LockFileName))) { + if (auto LockFileOwner = readLockFile(LockFileName)) { // Wipe out our unique lock file (it's useless now) sys::fs::remove(UniqueLockFileName); - return; + Owner = std::move(*LockFileOwner); + return false; } if (!sys::fs::exists(LockFileName)) { @@ -248,39 +246,14 @@ LockFileManager::LockFileManager(StringRef FileName) // There is a lock file that nobody owns; try to clean it up and get // ownership. - if ((EC = sys::fs::remove(LockFileName))) { - std::string S("failed to remove lockfile "); - S.append(std::string(UniqueLockFileName)); - setError(EC, S); - return; - } - } -} - -LockFileManager::LockFileState LockFileManager::getState() const { - if (Owner) - return LFS_Shared; - - if (ErrorCode) - return LFS_Error; - - return LFS_Owned; -} - -std::string LockFileManager::getErrorMessage() const { - if (ErrorCode) { - std::string Str(ErrorDiagMsg); - std::string ErrCodeMsg = ErrorCode.message(); - raw_string_ostream OSS(Str); - if (!ErrCodeMsg.empty()) - OSS << ": " << ErrCodeMsg; - return Str; + if ((EC = sys::fs::remove(LockFileName))) + return createStringError(EC, "failed to remove lockfile " + + UniqueLockFileName); } - return ""; } LockFileManager::~LockFileManager() { - if (getState() != LFS_Owned) + if (!std::holds_alternative<OwnedByUs>(Owner)) return; // Since we own the lock, remove the lock file and our own unique lock file. @@ -293,8 +266,9 @@ LockFileManager::~LockFileManager() { LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock(const unsigned MaxSeconds) { - if (getState() != LFS_Shared) - return Res_Success; + auto *LockFileOwner = std::get_if<OwnedByAnother>(&Owner); + assert(LockFileOwner && + "waiting for lock to be unlocked without knowing the owner"); // Since we don't yet have an event-based method to wait for the lock file, // use randomized exponential backoff, similar to Ethernet collision @@ -311,7 +285,8 @@ LockFileManager::waitForUnlock(const unsigned MaxSeconds) { return Res_Success; // If the process owning the lock died without cleaning up, just bail out. - if (!processStillExecuting((*Owner).first, (*Owner).second)) + if (!processStillExecuting(LockFileOwner->OwnerHostName, + LockFileOwner->OwnerPID)) return Res_OwnerDied; } |