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 <sys/stat.h>
26#include <sys/types.h>
27#include <system_error>
28#include
29
30#ifdef _WIN32
31#include <windows.h>
32#endif
33#if LLVM_ON_UNIX
34#include <unistd.h>
35#endif
36
37#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1050)
38#define USE_OSX_GETHOSTUUID 1
39#else
40#define USE_OSX_GETHOSTUUID 0
41#endif
42
43#if USE_OSX_GETHOSTUUID
44#include <uuid/uuid.h>
45#endif
46
47using namespace llvm;
48
49
50
51
52
53
54std::optional<std::pair<std::string, int>>
55LockFileManager::readLockFile(StringRef LockFileName) {
56
57
60 if (!MBOrErr) {
62 return std::nullopt;
63 }
65
68 std::tie(Hostname, PIDStr) = getToken(MB.getBuffer(), " ");
70 int PID;
72 auto Owner = std::make_pair(std::string(Hostname), PID);
73 if (processStillExecuting(Owner.first, Owner.second))
74 return Owner;
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
107 HostID.append(Dummy.begin(), Dummy.end());
108#endif
109
110 return std::error_code();
111}
112
113bool LockFileManager::processStillExecuting(StringRef HostID, int PID) {
114#if LLVM_ON_UNIX && !defined(__ANDROID__)
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:
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{
162 this->FileName = FileName;
164 std::string S("failed to obtain absolute path for ");
165 S.append(std::string(this->FileName));
167 return;
168 }
169 LockFileName = this->FileName;
170 LockFileName += ".lock";
171
172
173
174 if ((Owner = readLockFile(LockFileName)))
175 return;
176
177
178 UniqueLockFileName = LockFileName;
179 UniqueLockFileName += "-%%%%%%%%";
180 int UniqueLockFileID;
182 UniqueLockFileName, UniqueLockFileID, UniqueLockFileName)) {
183 std::string S("failed to create unique file ");
184 S.append(std::string(UniqueLockFileName));
186 return;
187 }
188
189
190 {
192 if (auto EC = getHostID(HostID)) {
193 setError(EC, "failed to get host id");
194 return;
195 }
196
197 raw_fd_ostream Out(UniqueLockFileID, true);
200
202
203
204 std::string S("failed to write to ");
205 S.append(std::string(UniqueLockFileName));
208
210 return;
211 }
212 }
213
214
215
216 RemoveUniqueLockFileOnSignal RemoveUniqueFile(UniqueLockFileName);
217
218 while (true) {
219
220 std::error_code EC =
222 if (!EC) {
223 RemoveUniqueFile.lockAcquired();
224 return;
225 }
226
228 std::string S("failed to create link ");
230 OSS << LockFileName.str() << " to " << UniqueLockFileName.str();
232 return;
233 }
234
235
236
237 if ((Owner = readLockFile(LockFileName))) {
238
240 return;
241 }
242
244
245
246 continue;
247 }
248
249
250
252 std::string S("failed to remove lockfile ");
253 S.append(std::string(UniqueLockFileName));
255 return;
256 }
257 }
258}
259
261 if (Owner)
263
264 if (ErrorCode)
266
268}
269
271 if (ErrorCode) {
272 std::string Str(ErrorDiagMsg);
273 std::string ErrCodeMsg = ErrorCode.message();
275 if (!ErrCodeMsg.empty())
276 OSS << ": " << ErrCodeMsg;
277 return Str;
278 }
279 return "";
280}
281
284 return;
285
286
289
290
292}
293
298
299
300
301
302
303 using namespace std::chrono_literals;
304 ExponentialBackoff Backoff(std::chrono::seconds(MaxSeconds), 10ms, 500ms);
305
306
308
311
315 }
316
317
318 if (!processStillExecuting((*Owner).first, (*Owner).second))
320 }
321
322
324}
325
328}
Provides ErrorOr smart pointer.
static std::error_code getHostID(SmallVectorImpl< char > &HostID)
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.
A class to help implement exponential backoff.
bool waitForNextAttempt()
Blocks while waiting for the next attempt.
LockFileState
Describes the state of a lock file.
@ LFS_Error
An error occurred while trying to create or find the lock file.
@ LFS_Owned
The lock file has been created and is owned by this instance of the object.
@ LFS_Shared
The lock file already exists and is owned by some other instance.
std::string getErrorMessage() const
Get error message, or "" if there is no error.
void setError(const std::error_code &EC, StringRef ErrorMsg="")
Set error and error message.
std::error_code unsafeRemoveLockFile()
Remove the lock file.
WaitForUnlockResult waitForUnlock(const unsigned MaxSeconds=90)
For a shared lock, wait until the owner releases the lock.
WaitForUnlockResult
Describes the result of waiting for the owner to release the lock.
@ Res_Success
The lock was released successfully.
@ Res_Timeout
Reached timeout while waiting for the owner to release the lock.
@ Res_OwnerDied
Owner died while holding the lock.
LockFileState getState() const
Determine the state of the lock file.
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...
StringRef str() const
Explicit conversion to StringRef.
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).
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.
A raw_ostream that writes to an std::string.
static Pid getProcessId()
Get the process's identifier.
std::error_code create_link(const Twine &to, const Twine &from)
Create a link from from to to.
void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
std::error_code access(const Twine &Path, AccessMode Mode)
Can the file be accessed?
bool exists(const basic_file_status &status)
Does file exist?
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.
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
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.
@ no_such_file_or_directory
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.