From 044eb2f6afba375a914ac9d8024f8f5142bb912e Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 18 Dec 2017 20:10:56 +0000 Subject: Vendor import of llvm trunk r321017: https://llvm.org/svn/llvm-project/llvm/trunk@321017 --- lib/Support/LockFileManager.cpp | 99 +++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 59 deletions(-) (limited to 'lib/Support/LockFileManager.cpp') diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp index 3ee3af7731e6..ec951f33a36a 100644 --- a/lib/Support/LockFileManager.cpp +++ b/lib/Support/LockFileManager.cpp @@ -123,33 +123,21 @@ bool LockFileManager::processStillExecuting(StringRef HostID, int PID) { namespace { -/// An RAII helper object ensure that the unique lock file is removed. -/// -/// Ensures that if there is an error or a signal before we finish acquiring the -/// lock, the unique file will be removed. And if we successfully take the lock, -/// the signal handler is left in place so that signals while the lock is held -/// will remove the unique lock file. The caller should ensure there is a -/// matching call to sys::DontRemoveFileOnSignal when the lock is released. -class RemoveUniqueLockFileOnSignal { - StringRef Filename; - bool RemoveImmediately; +/// An RAII helper object for cleanups. +class RAIICleanup { + std::function Fn; + bool Canceled = false; + public: - RemoveUniqueLockFileOnSignal(StringRef Name) - : Filename(Name), RemoveImmediately(true) { - sys::RemoveFileOnSignal(Filename, nullptr); - } + RAIICleanup(std::function Fn) : Fn(Fn) {} - ~RemoveUniqueLockFileOnSignal() { - if (!RemoveImmediately) { - // Leave the signal handler enabled. It will be removed when the lock is - // released. + ~RAIICleanup() { + if (Canceled) return; - } - sys::fs::remove(Filename); - sys::DontRemoveFileOnSignal(Filename); + Fn(); } - void lockAcquired() { RemoveImmediately = false; } + void cancel() { Canceled = true; } }; } // end anonymous namespace @@ -172,16 +160,22 @@ LockFileManager::LockFileManager(StringRef FileName) return; // 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(UniqueLockFileName.str()); + Expected Temp = + sys::fs::TempFile::create(LockFileName + "-%%%%%%%%"); + if (!Temp) { + std::error_code EC = errorToErrorCode(Temp.takeError()); + std::string S("failed to create unique file with prefix "); + S.append(LockFileName.str()); setError(EC, S); return; } + UniqueLockFile = std::move(*Temp); + + // Make sure we discard the temporary file on exit. + RAIICleanup RemoveTempFile([&]() { + if (Error E = UniqueLockFile->discard()) + setError(errorToErrorCode(std::move(E))); + }); // Write our process ID to our unique lock file. { @@ -191,55 +185,46 @@ LockFileManager::LockFileManager(StringRef FileName) return; } - raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true); + raw_fd_ostream Out(UniqueLockFile->FD, /*shouldClose=*/false); Out << HostID << ' '; #if LLVM_ON_UNIX Out << getpid(); #else Out << "1"; #endif - Out.close(); + Out.flush(); if (Out.has_error()) { - // We failed to write out PID, so make up an excuse, remove the + // We failed to write out PID, so report the error, remove the // unique lock file, and fail. - auto EC = make_error_code(errc::no_space_on_device); std::string S("failed to write to "); - S.append(UniqueLockFileName.str()); - setError(EC, S); - sys::fs::remove(UniqueLockFileName); + S.append(UniqueLockFile->TmpName); + setError(Out.error(), S); return; } } - // Clean up the unique file on signal, which also releases the lock if it is - // held since the .lock symlink will point to a nonexistent file. - RemoveUniqueLockFileOnSignal RemoveUniqueFile(UniqueLockFileName); - while (true) { // Create a link from the lock file name. If this succeeds, we're done. std::error_code EC = - sys::fs::create_link(UniqueLockFileName, LockFileName); + sys::fs::create_link(UniqueLockFile->TmpName, LockFileName); if (!EC) { - RemoveUniqueFile.lockAcquired(); + RemoveTempFile.cancel(); return; } if (EC != errc::file_exists) { std::string S("failed to create link "); raw_string_ostream OSS(S); - OSS << LockFileName.str() << " to " << UniqueLockFileName.str(); + OSS << LockFileName.str() << " to " << UniqueLockFile->TmpName; setError(EC, OSS.str()); return; } // 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); - return; - } + if ((Owner = readLockFile(LockFileName))) + return; // RemoveTempFile will delete out our unique lock file. if (!sys::fs::exists(LockFileName)) { // The previous owner released the lock file before we could read it. @@ -251,7 +236,7 @@ LockFileManager::LockFileManager(StringRef FileName) // ownership. if ((EC = sys::fs::remove(LockFileName))) { std::string S("failed to remove lockfile "); - S.append(UniqueLockFileName.str()); + S.append(LockFileName.str()); setError(EC, S); return; } @@ -262,21 +247,20 @@ LockFileManager::LockFileState LockFileManager::getState() const { if (Owner) return LFS_Shared; - if (Error) + if (ErrorCode) return LFS_Error; return LFS_Owned; } std::string LockFileManager::getErrorMessage() const { - if (Error) { + if (ErrorCode) { std::string Str(ErrorDiagMsg); - std::string ErrCodeMsg = Error->message(); + std::string ErrCodeMsg = ErrorCode.message(); raw_string_ostream OSS(Str); if (!ErrCodeMsg.empty()) - OSS << ": " << Error->message(); - OSS.flush(); - return Str; + OSS << ": " << ErrCodeMsg; + return OSS.str(); } return ""; } @@ -287,10 +271,7 @@ LockFileManager::~LockFileManager() { // Since we own the lock, remove the lock file and our own unique lock file. sys::fs::remove(LockFileName); - sys::fs::remove(UniqueLockFileName); - // The unique file is now gone, so remove it from the signal handler. This - // matches a sys::RemoveFileOnSignal() in LockFileManager(). - sys::DontRemoveFileOnSignal(UniqueLockFileName); + consumeError(UniqueLockFile->discard()); } LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() { -- cgit v1.2.3