LLVM: lib/Support/LockFileManager.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
12#include "llvm/Config/llvm-config.h"
21#include
22#include
23#include
24#include
25#include <system_error>
26#include
27
28#ifdef _WIN32
29#include <windows.h>
30#endif
31#if LLVM_ON_UNIX
32#include <unistd.h>
33#endif
34
35#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1050)
36#define USE_OSX_GETHOSTUUID 1
37#else
38#define USE_OSX_GETHOSTUUID 0
39#endif
40
41#if USE_OSX_GETHOSTUUID
42#include <uuid/uuid.h>
43#endif
44
45using namespace llvm;
46
47
48
49
50
51
52std::optionalLockFileManager::OwnedByAnother
53LockFileManager::readLockFile(StringRef LockFileName) {
54
55
58 if (!MBOrErr) {
60 return std::nullopt;
61 }
63
68 int PID;
70 OwnedByAnother Owner;
71 Owner.OwnerHostName = Hostname;
72 Owner.OwnerPID = PID;
73 if (processStillExecuting(Owner.OwnerHostName, Owner.OwnerPID))
75 }
76
77
79 return std::nullopt;
80}
81
84
85#if USE_OSX_GETHOSTUUID
86
87 struct timespec wait = {1, 0};
88 uuid_t uuid;
89 if (gethostuuid(uuid, &wait) != 0)
91
92 uuid_string_t UUIDStr;
93 uuid_unparse(uuid, UUIDStr);
96
97#elif LLVM_ON_UNIX
98 char HostName[256];
99 HostName[255] = 0;
100 HostName[0] = 0;
101 gethostname(HostName, 255);
103 HostID.append(HostNameRef.begin(), HostNameRef.end());
104
105#else
108#endif
109
110 return std::error_code();
111}
112
113bool LockFileManager::processStillExecuting(StringRef HostID, int PID) {
114#if LLVM_ON_UNIX && !defined(__ANDROID__)
115 SmallString<256> StoredHostID;
117 return true;
118
119
120 if (StoredHostID == HostID && getsid(PID) == -1 && errno == ESRCH)
121 return false;
122#endif
123
124 return true;
125}
126
127namespace {
128
129
130
131
132
133
134
135
136class RemoveUniqueLockFileOnSignal {
138 bool RemoveImmediately;
139public:
140 RemoveUniqueLockFileOnSignal(StringRef Name)
143 }
144
145 ~RemoveUniqueLockFileOnSignal() {
146 if (!RemoveImmediately) {
147
148
149 return;
150 }
153 }
154
155 void lockAcquired() { RemoveImmediately = false; }
156};
157
158}
159
160LockFileManager::LockFileManager(StringRef FileName)
161 : FileName(FileName), Owner(OwnerUnknown{}) {}
162
164 assert(std::holds_alternative(Owner) &&
165 "lock has already been attempted");
166
169 return createStringError(EC, "failed to obtain absolute path for " +
170 AbsoluteFileName);
171 LockFileName = AbsoluteFileName;
172 LockFileName += ".lock";
173
174
175
176 if (auto LockFileOwner = readLockFile(LockFileName)) {
177 Owner = std::move(*LockFileOwner);
178 return false;
179 }
180
181
182 UniqueLockFileName = LockFileName;
183 UniqueLockFileName += "-%%%%%%%%";
184 int UniqueLockFileID;
186 UniqueLockFileName, UniqueLockFileID, UniqueLockFileName))
188 UniqueLockFileName);
189
190
191 RemoveUniqueLockFileOnSignal RemoveUniqueFile(UniqueLockFileName);
192
193
194 {
198
199 raw_fd_ostream Out(UniqueLockFileID, true);
202
204
206 "failed to write to " + UniqueLockFileName);
207
209 return std::move(Err);
210 }
211 }
212
213 while (true) {
214
215 std::error_code EC =
217 if (!EC) {
218 RemoveUniqueFile.lockAcquired();
219 Owner = OwnedByUs{};
220 return true;
221 }
222
224 return createStringError(EC, "failed to create link " + LockFileName +
225 " to " + UniqueLockFileName);
226
227
228
229 if (auto LockFileOwner = readLockFile(LockFileName)) {
230 Owner = std::move(*LockFileOwner);
231 return false;
232 }
233
235
236
237 continue;
238 }
239
240
241
244 UniqueLockFileName);
245 }
246}
247
249 if (!std::holds_alternative(Owner))
250 return;
251
252
255
256
258}
259
262 auto *LockFileOwner = std::get_if(&Owner);
263 assert(LockFileOwner &&
264 "waiting for lock to be unlocked without knowing the owner");
265
266
267
268
269
270 using namespace std::chrono_literals;
272
273
275
279
280
281 if (!processStillExecuting(LockFileOwner->OwnerHostName,
282 LockFileOwner->OwnerPID))
284 }
285
286
288}
289
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static ManagedStatic< DebugCounterOwner > Owner
Provides ErrorOr smart pointer.
static std::error_code getHostID(SmallVectorImpl< char > &HostID)
Definition LockFileManager.cpp:82
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the SmallVector class.
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
A class to help implement exponential backoff.
LLVM_ABI bool waitForNextAttempt()
Blocks while waiting for the next attempt.
std::error_code unsafeMaybeUnlock() override
Remove the lock file.
Definition LockFileManager.cpp:290
WaitForUnlockResult waitForUnlockFor(std::chrono::seconds MaxSeconds) override
For a shared lock, wait until the owner releases the lock.
Definition LockFileManager.cpp:261
Expected< bool > tryLock() override
Tries to acquire the lock without blocking.
Definition LockFileManager.cpp:163
~LockFileManager() override
Unlocks the lock if previously acquired by tryLock().
Definition LockFileManager.cpp:248
This interface provides simple read-only access to a block of memory, and provides simple methods for...
StringRef getBuffer() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
StringRef - Represent a constant reference to a string, i.e.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
A raw_ostream that writes to a file descriptor.
bool has_error() const
Return the value of the flag in this raw_fd_ostream indicating whether an output error has been encou...
std::error_code error() const
void close()
Manually flush the stream and close the file.
void clear_error()
Set the flag read by has_error() to false.
static LLVM_ABI Pid getProcessId()
Get the process's identifier.
LLVM_ABI std::error_code access(const Twine &Path, AccessMode Mode)
Can the file be accessed?
LLVM_ABI bool exists(const basic_file_status &status)
Does file exist?
LLVM_ABI std::error_code create_link(const Twine &to, const Twine &from)
Create a link from from to to.
LLVM_ABI std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None, unsigned Mode=all_read|all_write)
Create a uniquely named file.
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
LLVM_ABI std::error_code make_absolute(SmallVectorImpl< char > &path)
Make path an absolute path.
LLVM_ABI void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
LLVM_ABI bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=nullptr)
This function registers signal handlers to ensure that if a signal gets delivered that the named file...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
@ no_such_file_or_directory
WaitForUnlockResult
Describes the result of waiting for the owner to release the lock.
@ Success
The lock was released successfully.
@ OwnerDied
Owner died while holding the lock.
@ Timeout
Reached timeout while waiting for the owner to release the lock.
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.