xref: /aosp_15_r20/external/llvm/lib/Support/LockFileManager.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===--- LockFileManager.cpp - File-level Locking Utility------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LockFileManager.h"
10*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Errc.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Signals.h"
16*9880d681SAndroid Build Coastguard Worker #include <sys/stat.h>
17*9880d681SAndroid Build Coastguard Worker #include <sys/types.h>
18*9880d681SAndroid Build Coastguard Worker #if LLVM_ON_WIN32
19*9880d681SAndroid Build Coastguard Worker #include <windows.h>
20*9880d681SAndroid Build Coastguard Worker #endif
21*9880d681SAndroid Build Coastguard Worker #if LLVM_ON_UNIX
22*9880d681SAndroid Build Coastguard Worker #include <unistd.h>
23*9880d681SAndroid Build Coastguard Worker #endif
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && (__MAC_OS_X_VERSION_MIN_REQUIRED > 1050)
26*9880d681SAndroid Build Coastguard Worker #define USE_OSX_GETHOSTUUID 1
27*9880d681SAndroid Build Coastguard Worker #else
28*9880d681SAndroid Build Coastguard Worker #define USE_OSX_GETHOSTUUID 0
29*9880d681SAndroid Build Coastguard Worker #endif
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker #if USE_OSX_GETHOSTUUID
32*9880d681SAndroid Build Coastguard Worker #include <uuid/uuid.h>
33*9880d681SAndroid Build Coastguard Worker #endif
34*9880d681SAndroid Build Coastguard Worker using namespace llvm;
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker /// \brief Attempt to read the lock file with the given name, if it exists.
37*9880d681SAndroid Build Coastguard Worker ///
38*9880d681SAndroid Build Coastguard Worker /// \param LockFileName The name of the lock file to read.
39*9880d681SAndroid Build Coastguard Worker ///
40*9880d681SAndroid Build Coastguard Worker /// \returns The process ID of the process that owns this lock file
41*9880d681SAndroid Build Coastguard Worker Optional<std::pair<std::string, int> >
readLockFile(StringRef LockFileName)42*9880d681SAndroid Build Coastguard Worker LockFileManager::readLockFile(StringRef LockFileName) {
43*9880d681SAndroid Build Coastguard Worker   // Read the owning host and PID out of the lock file. If it appears that the
44*9880d681SAndroid Build Coastguard Worker   // owning process is dead, the lock file is invalid.
45*9880d681SAndroid Build Coastguard Worker   ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
46*9880d681SAndroid Build Coastguard Worker       MemoryBuffer::getFile(LockFileName);
47*9880d681SAndroid Build Coastguard Worker   if (!MBOrErr) {
48*9880d681SAndroid Build Coastguard Worker     sys::fs::remove(LockFileName);
49*9880d681SAndroid Build Coastguard Worker     return None;
50*9880d681SAndroid Build Coastguard Worker   }
51*9880d681SAndroid Build Coastguard Worker   MemoryBuffer &MB = *MBOrErr.get();
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   StringRef Hostname;
54*9880d681SAndroid Build Coastguard Worker   StringRef PIDStr;
55*9880d681SAndroid Build Coastguard Worker   std::tie(Hostname, PIDStr) = getToken(MB.getBuffer(), " ");
56*9880d681SAndroid Build Coastguard Worker   PIDStr = PIDStr.substr(PIDStr.find_first_not_of(" "));
57*9880d681SAndroid Build Coastguard Worker   int PID;
58*9880d681SAndroid Build Coastguard Worker   if (!PIDStr.getAsInteger(10, PID)) {
59*9880d681SAndroid Build Coastguard Worker     auto Owner = std::make_pair(std::string(Hostname), PID);
60*9880d681SAndroid Build Coastguard Worker     if (processStillExecuting(Owner.first, Owner.second))
61*9880d681SAndroid Build Coastguard Worker       return Owner;
62*9880d681SAndroid Build Coastguard Worker   }
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker   // Delete the lock file. It's invalid anyway.
65*9880d681SAndroid Build Coastguard Worker   sys::fs::remove(LockFileName);
66*9880d681SAndroid Build Coastguard Worker   return None;
67*9880d681SAndroid Build Coastguard Worker }
68*9880d681SAndroid Build Coastguard Worker 
getHostID(SmallVectorImpl<char> & HostID)69*9880d681SAndroid Build Coastguard Worker static std::error_code getHostID(SmallVectorImpl<char> &HostID) {
70*9880d681SAndroid Build Coastguard Worker   HostID.clear();
71*9880d681SAndroid Build Coastguard Worker 
72*9880d681SAndroid Build Coastguard Worker #if USE_OSX_GETHOSTUUID
73*9880d681SAndroid Build Coastguard Worker   // On OS X, use the more stable hardware UUID instead of hostname.
74*9880d681SAndroid Build Coastguard Worker   struct timespec wait = {1, 0}; // 1 second.
75*9880d681SAndroid Build Coastguard Worker   uuid_t uuid;
76*9880d681SAndroid Build Coastguard Worker   if (gethostuuid(uuid, &wait) != 0)
77*9880d681SAndroid Build Coastguard Worker     return std::error_code(errno, std::system_category());
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker   uuid_string_t UUIDStr;
80*9880d681SAndroid Build Coastguard Worker   uuid_unparse(uuid, UUIDStr);
81*9880d681SAndroid Build Coastguard Worker   StringRef UUIDRef(UUIDStr);
82*9880d681SAndroid Build Coastguard Worker   HostID.append(UUIDRef.begin(), UUIDRef.end());
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker #elif LLVM_ON_UNIX
85*9880d681SAndroid Build Coastguard Worker   char HostName[256];
86*9880d681SAndroid Build Coastguard Worker   HostName[255] = 0;
87*9880d681SAndroid Build Coastguard Worker   HostName[0] = 0;
88*9880d681SAndroid Build Coastguard Worker   gethostname(HostName, 255);
89*9880d681SAndroid Build Coastguard Worker   StringRef HostNameRef(HostName);
90*9880d681SAndroid Build Coastguard Worker   HostID.append(HostNameRef.begin(), HostNameRef.end());
91*9880d681SAndroid Build Coastguard Worker 
92*9880d681SAndroid Build Coastguard Worker #else
93*9880d681SAndroid Build Coastguard Worker   StringRef Dummy("localhost");
94*9880d681SAndroid Build Coastguard Worker   HostID.append(Dummy.begin(), Dummy.end());
95*9880d681SAndroid Build Coastguard Worker #endif
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker   return std::error_code();
98*9880d681SAndroid Build Coastguard Worker }
99*9880d681SAndroid Build Coastguard Worker 
processStillExecuting(StringRef HostID,int PID)100*9880d681SAndroid Build Coastguard Worker bool LockFileManager::processStillExecuting(StringRef HostID, int PID) {
101*9880d681SAndroid Build Coastguard Worker #if LLVM_ON_UNIX && !defined(__ANDROID__)
102*9880d681SAndroid Build Coastguard Worker   SmallString<256> StoredHostID;
103*9880d681SAndroid Build Coastguard Worker   if (getHostID(StoredHostID))
104*9880d681SAndroid Build Coastguard Worker     return true; // Conservatively assume it's executing on error.
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker   // Check whether the process is dead. If so, we're done.
107*9880d681SAndroid Build Coastguard Worker   if (StoredHostID == HostID && getsid(PID) == -1 && errno == ESRCH)
108*9880d681SAndroid Build Coastguard Worker     return false;
109*9880d681SAndroid Build Coastguard Worker #endif
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   return true;
112*9880d681SAndroid Build Coastguard Worker }
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker namespace {
115*9880d681SAndroid Build Coastguard Worker /// An RAII helper object ensure that the unique lock file is removed.
116*9880d681SAndroid Build Coastguard Worker ///
117*9880d681SAndroid Build Coastguard Worker /// Ensures that if there is an error or a signal before we finish acquiring the
118*9880d681SAndroid Build Coastguard Worker /// lock, the unique file will be removed. And if we successfully take the lock,
119*9880d681SAndroid Build Coastguard Worker /// the signal handler is left in place so that signals while the lock is held
120*9880d681SAndroid Build Coastguard Worker /// will remove the unique lock file. The caller should ensure there is a
121*9880d681SAndroid Build Coastguard Worker /// matching call to sys::DontRemoveFileOnSignal when the lock is released.
122*9880d681SAndroid Build Coastguard Worker class RemoveUniqueLockFileOnSignal {
123*9880d681SAndroid Build Coastguard Worker   StringRef Filename;
124*9880d681SAndroid Build Coastguard Worker   bool RemoveImmediately;
125*9880d681SAndroid Build Coastguard Worker public:
RemoveUniqueLockFileOnSignal(StringRef Name)126*9880d681SAndroid Build Coastguard Worker   RemoveUniqueLockFileOnSignal(StringRef Name)
127*9880d681SAndroid Build Coastguard Worker   : Filename(Name), RemoveImmediately(true) {
128*9880d681SAndroid Build Coastguard Worker     sys::RemoveFileOnSignal(Filename, nullptr);
129*9880d681SAndroid Build Coastguard Worker   }
~RemoveUniqueLockFileOnSignal()130*9880d681SAndroid Build Coastguard Worker   ~RemoveUniqueLockFileOnSignal() {
131*9880d681SAndroid Build Coastguard Worker     if (!RemoveImmediately) {
132*9880d681SAndroid Build Coastguard Worker       // Leave the signal handler enabled. It will be removed when the lock is
133*9880d681SAndroid Build Coastguard Worker       // released.
134*9880d681SAndroid Build Coastguard Worker       return;
135*9880d681SAndroid Build Coastguard Worker     }
136*9880d681SAndroid Build Coastguard Worker     sys::fs::remove(Filename);
137*9880d681SAndroid Build Coastguard Worker     sys::DontRemoveFileOnSignal(Filename);
138*9880d681SAndroid Build Coastguard Worker   }
lockAcquired()139*9880d681SAndroid Build Coastguard Worker   void lockAcquired() { RemoveImmediately = false; }
140*9880d681SAndroid Build Coastguard Worker };
141*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
142*9880d681SAndroid Build Coastguard Worker 
LockFileManager(StringRef FileName)143*9880d681SAndroid Build Coastguard Worker LockFileManager::LockFileManager(StringRef FileName)
144*9880d681SAndroid Build Coastguard Worker {
145*9880d681SAndroid Build Coastguard Worker   this->FileName = FileName;
146*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = sys::fs::make_absolute(this->FileName)) {
147*9880d681SAndroid Build Coastguard Worker     std::string S("failed to obtain absolute path for ");
148*9880d681SAndroid Build Coastguard Worker     S.append(this->FileName.str());
149*9880d681SAndroid Build Coastguard Worker     setError(EC, S);
150*9880d681SAndroid Build Coastguard Worker     return;
151*9880d681SAndroid Build Coastguard Worker   }
152*9880d681SAndroid Build Coastguard Worker   LockFileName = this->FileName;
153*9880d681SAndroid Build Coastguard Worker   LockFileName += ".lock";
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker   // If the lock file already exists, don't bother to try to create our own
156*9880d681SAndroid Build Coastguard Worker   // lock file; it won't work anyway. Just figure out who owns this lock file.
157*9880d681SAndroid Build Coastguard Worker   if ((Owner = readLockFile(LockFileName)))
158*9880d681SAndroid Build Coastguard Worker     return;
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker   // Create a lock file that is unique to this instance.
161*9880d681SAndroid Build Coastguard Worker   UniqueLockFileName = LockFileName;
162*9880d681SAndroid Build Coastguard Worker   UniqueLockFileName += "-%%%%%%%%";
163*9880d681SAndroid Build Coastguard Worker   int UniqueLockFileID;
164*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = sys::fs::createUniqueFile(
165*9880d681SAndroid Build Coastguard Worker           UniqueLockFileName, UniqueLockFileID, UniqueLockFileName)) {
166*9880d681SAndroid Build Coastguard Worker     std::string S("failed to create unique file ");
167*9880d681SAndroid Build Coastguard Worker     S.append(UniqueLockFileName.str());
168*9880d681SAndroid Build Coastguard Worker     setError(EC, S);
169*9880d681SAndroid Build Coastguard Worker     return;
170*9880d681SAndroid Build Coastguard Worker   }
171*9880d681SAndroid Build Coastguard Worker 
172*9880d681SAndroid Build Coastguard Worker   // Write our process ID to our unique lock file.
173*9880d681SAndroid Build Coastguard Worker   {
174*9880d681SAndroid Build Coastguard Worker     SmallString<256> HostID;
175*9880d681SAndroid Build Coastguard Worker     if (auto EC = getHostID(HostID)) {
176*9880d681SAndroid Build Coastguard Worker       setError(EC, "failed to get host id");
177*9880d681SAndroid Build Coastguard Worker       return;
178*9880d681SAndroid Build Coastguard Worker     }
179*9880d681SAndroid Build Coastguard Worker 
180*9880d681SAndroid Build Coastguard Worker     raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true);
181*9880d681SAndroid Build Coastguard Worker     Out << HostID << ' ';
182*9880d681SAndroid Build Coastguard Worker #if LLVM_ON_UNIX
183*9880d681SAndroid Build Coastguard Worker     Out << getpid();
184*9880d681SAndroid Build Coastguard Worker #else
185*9880d681SAndroid Build Coastguard Worker     Out << "1";
186*9880d681SAndroid Build Coastguard Worker #endif
187*9880d681SAndroid Build Coastguard Worker     Out.close();
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker     if (Out.has_error()) {
190*9880d681SAndroid Build Coastguard Worker       // We failed to write out PID, so make up an excuse, remove the
191*9880d681SAndroid Build Coastguard Worker       // unique lock file, and fail.
192*9880d681SAndroid Build Coastguard Worker       auto EC = make_error_code(errc::no_space_on_device);
193*9880d681SAndroid Build Coastguard Worker       std::string S("failed to write to ");
194*9880d681SAndroid Build Coastguard Worker       S.append(UniqueLockFileName.str());
195*9880d681SAndroid Build Coastguard Worker       setError(EC, S);
196*9880d681SAndroid Build Coastguard Worker       sys::fs::remove(UniqueLockFileName);
197*9880d681SAndroid Build Coastguard Worker       return;
198*9880d681SAndroid Build Coastguard Worker     }
199*9880d681SAndroid Build Coastguard Worker   }
200*9880d681SAndroid Build Coastguard Worker 
201*9880d681SAndroid Build Coastguard Worker   // Clean up the unique file on signal, which also releases the lock if it is
202*9880d681SAndroid Build Coastguard Worker   // held since the .lock symlink will point to a nonexistent file.
203*9880d681SAndroid Build Coastguard Worker   RemoveUniqueLockFileOnSignal RemoveUniqueFile(UniqueLockFileName);
204*9880d681SAndroid Build Coastguard Worker 
205*9880d681SAndroid Build Coastguard Worker   while (1) {
206*9880d681SAndroid Build Coastguard Worker     // Create a link from the lock file name. If this succeeds, we're done.
207*9880d681SAndroid Build Coastguard Worker     std::error_code EC =
208*9880d681SAndroid Build Coastguard Worker         sys::fs::create_link(UniqueLockFileName, LockFileName);
209*9880d681SAndroid Build Coastguard Worker     if (!EC) {
210*9880d681SAndroid Build Coastguard Worker       RemoveUniqueFile.lockAcquired();
211*9880d681SAndroid Build Coastguard Worker       return;
212*9880d681SAndroid Build Coastguard Worker     }
213*9880d681SAndroid Build Coastguard Worker 
214*9880d681SAndroid Build Coastguard Worker     if (EC != errc::file_exists) {
215*9880d681SAndroid Build Coastguard Worker       std::string S("failed to create link ");
216*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OSS(S);
217*9880d681SAndroid Build Coastguard Worker       OSS << LockFileName.str() << " to " << UniqueLockFileName.str();
218*9880d681SAndroid Build Coastguard Worker       setError(EC, OSS.str());
219*9880d681SAndroid Build Coastguard Worker       return;
220*9880d681SAndroid Build Coastguard Worker     }
221*9880d681SAndroid Build Coastguard Worker 
222*9880d681SAndroid Build Coastguard Worker     // Someone else managed to create the lock file first. Read the process ID
223*9880d681SAndroid Build Coastguard Worker     // from the lock file.
224*9880d681SAndroid Build Coastguard Worker     if ((Owner = readLockFile(LockFileName))) {
225*9880d681SAndroid Build Coastguard Worker       // Wipe out our unique lock file (it's useless now)
226*9880d681SAndroid Build Coastguard Worker       sys::fs::remove(UniqueLockFileName);
227*9880d681SAndroid Build Coastguard Worker       return;
228*9880d681SAndroid Build Coastguard Worker     }
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker     if (!sys::fs::exists(LockFileName)) {
231*9880d681SAndroid Build Coastguard Worker       // The previous owner released the lock file before we could read it.
232*9880d681SAndroid Build Coastguard Worker       // Try to get ownership again.
233*9880d681SAndroid Build Coastguard Worker       continue;
234*9880d681SAndroid Build Coastguard Worker     }
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker     // There is a lock file that nobody owns; try to clean it up and get
237*9880d681SAndroid Build Coastguard Worker     // ownership.
238*9880d681SAndroid Build Coastguard Worker     if ((EC = sys::fs::remove(LockFileName))) {
239*9880d681SAndroid Build Coastguard Worker       std::string S("failed to remove lockfile ");
240*9880d681SAndroid Build Coastguard Worker       S.append(UniqueLockFileName.str());
241*9880d681SAndroid Build Coastguard Worker       setError(EC, S);
242*9880d681SAndroid Build Coastguard Worker       return;
243*9880d681SAndroid Build Coastguard Worker     }
244*9880d681SAndroid Build Coastguard Worker   }
245*9880d681SAndroid Build Coastguard Worker }
246*9880d681SAndroid Build Coastguard Worker 
getState() const247*9880d681SAndroid Build Coastguard Worker LockFileManager::LockFileState LockFileManager::getState() const {
248*9880d681SAndroid Build Coastguard Worker   if (Owner)
249*9880d681SAndroid Build Coastguard Worker     return LFS_Shared;
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker   if (Error)
252*9880d681SAndroid Build Coastguard Worker     return LFS_Error;
253*9880d681SAndroid Build Coastguard Worker 
254*9880d681SAndroid Build Coastguard Worker   return LFS_Owned;
255*9880d681SAndroid Build Coastguard Worker }
256*9880d681SAndroid Build Coastguard Worker 
getErrorMessage() const257*9880d681SAndroid Build Coastguard Worker std::string LockFileManager::getErrorMessage() const {
258*9880d681SAndroid Build Coastguard Worker   if (Error) {
259*9880d681SAndroid Build Coastguard Worker     std::string Str(ErrorDiagMsg);
260*9880d681SAndroid Build Coastguard Worker     std::string ErrCodeMsg = Error->message();
261*9880d681SAndroid Build Coastguard Worker     raw_string_ostream OSS(Str);
262*9880d681SAndroid Build Coastguard Worker     if (!ErrCodeMsg.empty())
263*9880d681SAndroid Build Coastguard Worker       OSS << ": " << Error->message();
264*9880d681SAndroid Build Coastguard Worker     OSS.flush();
265*9880d681SAndroid Build Coastguard Worker     return Str;
266*9880d681SAndroid Build Coastguard Worker   }
267*9880d681SAndroid Build Coastguard Worker   return "";
268*9880d681SAndroid Build Coastguard Worker }
269*9880d681SAndroid Build Coastguard Worker 
~LockFileManager()270*9880d681SAndroid Build Coastguard Worker LockFileManager::~LockFileManager() {
271*9880d681SAndroid Build Coastguard Worker   if (getState() != LFS_Owned)
272*9880d681SAndroid Build Coastguard Worker     return;
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   // Since we own the lock, remove the lock file and our own unique lock file.
275*9880d681SAndroid Build Coastguard Worker   sys::fs::remove(LockFileName);
276*9880d681SAndroid Build Coastguard Worker   sys::fs::remove(UniqueLockFileName);
277*9880d681SAndroid Build Coastguard Worker   // The unique file is now gone, so remove it from the signal handler. This
278*9880d681SAndroid Build Coastguard Worker   // matches a sys::RemoveFileOnSignal() in LockFileManager().
279*9880d681SAndroid Build Coastguard Worker   sys::DontRemoveFileOnSignal(UniqueLockFileName);
280*9880d681SAndroid Build Coastguard Worker }
281*9880d681SAndroid Build Coastguard Worker 
waitForUnlock()282*9880d681SAndroid Build Coastguard Worker LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
283*9880d681SAndroid Build Coastguard Worker   if (getState() != LFS_Shared)
284*9880d681SAndroid Build Coastguard Worker     return Res_Success;
285*9880d681SAndroid Build Coastguard Worker 
286*9880d681SAndroid Build Coastguard Worker #if LLVM_ON_WIN32
287*9880d681SAndroid Build Coastguard Worker   unsigned long Interval = 1;
288*9880d681SAndroid Build Coastguard Worker #else
289*9880d681SAndroid Build Coastguard Worker   struct timespec Interval;
290*9880d681SAndroid Build Coastguard Worker   Interval.tv_sec = 0;
291*9880d681SAndroid Build Coastguard Worker   Interval.tv_nsec = 1000000;
292*9880d681SAndroid Build Coastguard Worker #endif
293*9880d681SAndroid Build Coastguard Worker   // Don't wait more than five minutes per iteration. Total timeout for the file
294*9880d681SAndroid Build Coastguard Worker   // to appear is ~8.5 mins.
295*9880d681SAndroid Build Coastguard Worker   const unsigned MaxSeconds = 5*60;
296*9880d681SAndroid Build Coastguard Worker   do {
297*9880d681SAndroid Build Coastguard Worker     // Sleep for the designated interval, to allow the owning process time to
298*9880d681SAndroid Build Coastguard Worker     // finish up and remove the lock file.
299*9880d681SAndroid Build Coastguard Worker     // FIXME: Should we hook in to system APIs to get a notification when the
300*9880d681SAndroid Build Coastguard Worker     // lock file is deleted?
301*9880d681SAndroid Build Coastguard Worker #if LLVM_ON_WIN32
302*9880d681SAndroid Build Coastguard Worker     Sleep(Interval);
303*9880d681SAndroid Build Coastguard Worker #else
304*9880d681SAndroid Build Coastguard Worker     nanosleep(&Interval, nullptr);
305*9880d681SAndroid Build Coastguard Worker #endif
306*9880d681SAndroid Build Coastguard Worker 
307*9880d681SAndroid Build Coastguard Worker     if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) ==
308*9880d681SAndroid Build Coastguard Worker         errc::no_such_file_or_directory) {
309*9880d681SAndroid Build Coastguard Worker       // If the original file wasn't created, somone thought the lock was dead.
310*9880d681SAndroid Build Coastguard Worker       if (!sys::fs::exists(FileName))
311*9880d681SAndroid Build Coastguard Worker         return Res_OwnerDied;
312*9880d681SAndroid Build Coastguard Worker       return Res_Success;
313*9880d681SAndroid Build Coastguard Worker     }
314*9880d681SAndroid Build Coastguard Worker 
315*9880d681SAndroid Build Coastguard Worker     // If the process owning the lock died without cleaning up, just bail out.
316*9880d681SAndroid Build Coastguard Worker     if (!processStillExecuting((*Owner).first, (*Owner).second))
317*9880d681SAndroid Build Coastguard Worker       return Res_OwnerDied;
318*9880d681SAndroid Build Coastguard Worker 
319*9880d681SAndroid Build Coastguard Worker     // Exponentially increase the time we wait for the lock to be removed.
320*9880d681SAndroid Build Coastguard Worker #if LLVM_ON_WIN32
321*9880d681SAndroid Build Coastguard Worker     Interval *= 2;
322*9880d681SAndroid Build Coastguard Worker #else
323*9880d681SAndroid Build Coastguard Worker     Interval.tv_sec *= 2;
324*9880d681SAndroid Build Coastguard Worker     Interval.tv_nsec *= 2;
325*9880d681SAndroid Build Coastguard Worker     if (Interval.tv_nsec >= 1000000000) {
326*9880d681SAndroid Build Coastguard Worker       ++Interval.tv_sec;
327*9880d681SAndroid Build Coastguard Worker       Interval.tv_nsec -= 1000000000;
328*9880d681SAndroid Build Coastguard Worker     }
329*9880d681SAndroid Build Coastguard Worker #endif
330*9880d681SAndroid Build Coastguard Worker   } while (
331*9880d681SAndroid Build Coastguard Worker #if LLVM_ON_WIN32
332*9880d681SAndroid Build Coastguard Worker            Interval < MaxSeconds * 1000
333*9880d681SAndroid Build Coastguard Worker #else
334*9880d681SAndroid Build Coastguard Worker            Interval.tv_sec < (time_t)MaxSeconds
335*9880d681SAndroid Build Coastguard Worker #endif
336*9880d681SAndroid Build Coastguard Worker            );
337*9880d681SAndroid Build Coastguard Worker 
338*9880d681SAndroid Build Coastguard Worker   // Give up.
339*9880d681SAndroid Build Coastguard Worker   return Res_Timeout;
340*9880d681SAndroid Build Coastguard Worker }
341*9880d681SAndroid Build Coastguard Worker 
unsafeRemoveLockFile()342*9880d681SAndroid Build Coastguard Worker std::error_code LockFileManager::unsafeRemoveLockFile() {
343*9880d681SAndroid Build Coastguard Worker   return sys::fs::remove(LockFileName);
344*9880d681SAndroid Build Coastguard Worker }
345