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 &current_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.