@@ -51,7 +51,7 @@ using namespace llvm;
51
51
// / \param LockFileName The name of the lock file to read.
52
52
// /
53
53
// / \returns The process ID of the process that owns this lock file
54
- std::optional<std::pair<std::string, int > >
54
+ std::optional<LockFileManager::OwnedByAnother >
55
55
LockFileManager::readLockFile (StringRef LockFileName) {
56
56
// Read the owning host and PID out of the lock file. If it appears that the
57
57
// owning process is dead, the lock file is invalid.
@@ -69,8 +69,10 @@ LockFileManager::readLockFile(StringRef LockFileName) {
69
69
PIDStr = PIDStr.substr (PIDStr.find_first_not_of (' ' ));
70
70
int PID;
71
71
if (!PIDStr.getAsInteger (10 , PID)) {
72
- auto Owner = std::make_pair (std::string (Hostname), PID);
73
- if (processStillExecuting (Owner.first , Owner.second ))
72
+ OwnedByAnother Owner;
73
+ Owner.OwnerHostName = Hostname;
74
+ Owner.OwnerPID = PID;
75
+ if (processStillExecuting (Owner.OwnerHostName , Owner.OwnerPID ))
74
76
return Owner;
75
77
}
76
78
@@ -158,41 +160,40 @@ class RemoveUniqueLockFileOnSignal {
158
160
} // end anonymous namespace
159
161
160
162
LockFileManager::LockFileManager (StringRef FileName)
161
- {
162
- this ->FileName = FileName;
163
- if (std::error_code EC = sys::fs::make_absolute (this ->FileName )) {
164
- std::string S (" failed to obtain absolute path for " );
165
- S.append (std::string (this ->FileName ));
166
- setError (EC, S);
167
- return ;
168
- }
169
- LockFileName = this ->FileName ;
163
+ : FileName(FileName), Owner(OwnerUnknown{}) {}
164
+
165
+ Expected<bool > LockFileManager::tryLock () {
166
+ assert (std::holds_alternative<OwnerUnknown>(Owner) &&
167
+ " lock has already been attempted" );
168
+
169
+ SmallString<128 > AbsoluteFileName (FileName);
170
+ if (std::error_code EC = sys::fs::make_absolute (AbsoluteFileName))
171
+ return createStringError (EC, " failed to obtain absolute path for " +
172
+ AbsoluteFileName);
173
+ LockFileName = AbsoluteFileName;
170
174
LockFileName += " .lock" ;
171
175
172
176
// If the lock file already exists, don't bother to try to create our own
173
177
// lock file; it won't work anyway. Just figure out who owns this lock file.
174
- if ((Owner = readLockFile (LockFileName)))
175
- return ;
178
+ if (auto LockFileOwner = readLockFile (LockFileName)) {
179
+ Owner = std::move (*LockFileOwner);
180
+ return false ;
181
+ }
176
182
177
183
// Create a lock file that is unique to this instance.
178
184
UniqueLockFileName = LockFileName;
179
185
UniqueLockFileName += " -%%%%%%%%" ;
180
186
int UniqueLockFileID;
181
187
if (std::error_code EC = sys::fs::createUniqueFile (
182
- UniqueLockFileName, UniqueLockFileID, UniqueLockFileName)) {
183
- std::string S (" failed to create unique file " );
184
- S.append (std::string (UniqueLockFileName));
185
- setError (EC, S);
186
- return ;
187
- }
188
+ UniqueLockFileName, UniqueLockFileID, UniqueLockFileName))
189
+ return createStringError (EC, " failed to create unique file " +
190
+ UniqueLockFileName);
188
191
189
192
// Write our process ID to our unique lock file.
190
193
{
191
194
SmallString<256 > HostID;
192
- if (auto EC = getHostID (HostID)) {
193
- setError (EC, " failed to get host id" );
194
- return ;
195
- }
195
+ if (auto EC = getHostID (HostID))
196
+ return createStringError (EC, " failed to get host id" );
196
197
197
198
raw_fd_ostream Out (UniqueLockFileID, /* shouldClose=*/ true );
198
199
Out << HostID << ' ' << sys::Process::getProcessId ();
@@ -201,13 +202,12 @@ LockFileManager::LockFileManager(StringRef FileName)
201
202
if (Out.has_error ()) {
202
203
// We failed to write out PID, so report the error, remove the
203
204
// unique lock file, and fail.
204
- std::string S (" failed to write to " );
205
- S.append (std::string (UniqueLockFileName));
206
- setError (Out.error (), S);
205
+ Error Err = createStringError (Out.error (),
206
+ " failed to write to " + UniqueLockFileName);
207
207
sys::fs::remove (UniqueLockFileName);
208
208
// Don't call report_fatal_error.
209
209
Out.clear_error ();
210
- return ;
210
+ return std::move (Err) ;
211
211
}
212
212
}
213
213
@@ -221,23 +221,21 @@ LockFileManager::LockFileManager(StringRef FileName)
221
221
sys::fs::create_link (UniqueLockFileName, LockFileName);
222
222
if (!EC) {
223
223
RemoveUniqueFile.lockAcquired ();
224
- return ;
224
+ Owner = OwnedByUs{};
225
+ return true ;
225
226
}
226
227
227
- if (EC != errc::file_exists) {
228
- std::string S (" failed to create link " );
229
- raw_string_ostream OSS (S);
230
- OSS << LockFileName.str () << " to " << UniqueLockFileName.str ();
231
- setError (EC, S);
232
- return ;
233
- }
228
+ if (EC != errc::file_exists)
229
+ return createStringError (EC, " failed to create link " + LockFileName +
230
+ " to " + UniqueLockFileName);
234
231
235
232
// Someone else managed to create the lock file first. Read the process ID
236
233
// from the lock file.
237
- if ((Owner = readLockFile (LockFileName) )) {
234
+ if (auto LockFileOwner = readLockFile (LockFileName)) {
238
235
// Wipe out our unique lock file (it's useless now)
239
236
sys::fs::remove (UniqueLockFileName);
240
- return ;
237
+ Owner = std::move (*LockFileOwner);
238
+ return false ;
241
239
}
242
240
243
241
if (!sys::fs::exists (LockFileName)) {
@@ -248,39 +246,14 @@ LockFileManager::LockFileManager(StringRef FileName)
248
246
249
247
// There is a lock file that nobody owns; try to clean it up and get
250
248
// ownership.
251
- if ((EC = sys::fs::remove (LockFileName))) {
252
- std::string S (" failed to remove lockfile " );
253
- S.append (std::string (UniqueLockFileName));
254
- setError (EC, S);
255
- return ;
256
- }
257
- }
258
- }
259
-
260
- LockFileManager::LockFileState LockFileManager::getState () const {
261
- if (Owner)
262
- return LFS_Shared;
263
-
264
- if (ErrorCode)
265
- return LFS_Error;
266
-
267
- return LFS_Owned;
268
- }
269
-
270
- std::string LockFileManager::getErrorMessage () const {
271
- if (ErrorCode) {
272
- std::string Str (ErrorDiagMsg);
273
- std::string ErrCodeMsg = ErrorCode.message ();
274
- raw_string_ostream OSS (Str);
275
- if (!ErrCodeMsg.empty ())
276
- OSS << " : " << ErrCodeMsg;
277
- return Str;
249
+ if ((EC = sys::fs::remove (LockFileName)))
250
+ return createStringError (EC, " failed to remove lockfile " +
251
+ UniqueLockFileName);
278
252
}
279
- return " " ;
280
253
}
281
254
282
255
LockFileManager::~LockFileManager () {
283
- if (getState () != LFS_Owned )
256
+ if (!std::holds_alternative<OwnedByUs>(Owner) )
284
257
return ;
285
258
286
259
// Since we own the lock, remove the lock file and our own unique lock file.
@@ -293,8 +266,9 @@ LockFileManager::~LockFileManager() {
293
266
294
267
LockFileManager::WaitForUnlockResult
295
268
LockFileManager::waitForUnlock (const unsigned MaxSeconds) {
296
- if (getState () != LFS_Shared)
297
- return Res_Success;
269
+ auto *LockFileOwner = std::get_if<OwnedByAnother>(&Owner);
270
+ assert (LockFileOwner &&
271
+ " waiting for lock to be unlocked without knowing the owner" );
298
272
299
273
// Since we don't yet have an event-based method to wait for the lock file,
300
274
// use randomized exponential backoff, similar to Ethernet collision
@@ -311,7 +285,8 @@ LockFileManager::waitForUnlock(const unsigned MaxSeconds) {
311
285
return Res_Success;
312
286
313
287
// If the process owning the lock died without cleaning up, just bail out.
314
- if (!processStillExecuting ((*Owner).first , (*Owner).second ))
288
+ if (!processStillExecuting (LockFileOwner->OwnerHostName ,
289
+ LockFileOwner->OwnerPID ))
315
290
return Res_OwnerDied;
316
291
}
317
292
0 commit comments