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.