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