195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//===--- LockFileManager.cpp - File-level Locking Utility------------------===//
295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//
395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//                     The LLVM Compiler Infrastructure
495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//
595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor// This file is distributed under the University of Illinois Open Source
695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor// License. See LICENSE.TXT for details.
795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//
895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor//===----------------------------------------------------------------------===//
995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include "llvm/Support/LockFileManager.h"
1095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include "llvm/Support/FileSystem.h"
1195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include "llvm/Support/raw_ostream.h"
1295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include <fstream>
1395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include <sys/types.h>
1495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include <sys/stat.h>
1595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#if LLVM_ON_WIN32
1695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include <windows.h>
1795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
1895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#if LLVM_ON_UNIX
1995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#include <unistd.h>
2095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
2195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregorusing namespace llvm;
2295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
2395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// \brief Attempt to read the lock file with the given name, if it exists.
2495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor///
2595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// \param LockFileName The name of the lock file to read.
2695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor///
2795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor/// \returns The process ID of the process that owns this lock file
2895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas GregorOptional<std::pair<std::string, int> >
2995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas GregorLockFileManager::readLockFile(StringRef LockFileName) {
3095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Check whether the lock file exists. If not, clearly there's nothing
3195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // to read, so we just return.
3295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  bool Exists = false;
3395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (sys::fs::exists(LockFileName, Exists) || !Exists)
3495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return Optional<std::pair<std::string, int> >();
3595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
3695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Read the owning host and PID out of the lock file. If it appears that the
3795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // owning process is dead, the lock file is invalid.
3895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  int PID = 0;
3995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  std::string Hostname;
4095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  std::ifstream Input(LockFileName.str().c_str());
4195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (Input >> Hostname >> PID && PID > 0 &&
4295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      processStillExecuting(Hostname, PID))
4395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return std::make_pair(Hostname, PID);
4495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
4595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Delete the lock file. It's invalid anyway.
4695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  bool Existed;
4795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  sys::fs::remove(LockFileName, Existed);
4895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  return Optional<std::pair<std::string, int> >();
4995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor}
5095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
5195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregorbool LockFileManager::processStillExecuting(StringRef Hostname, int PID) {
5268d92bdcc99e647546f40cfce5cfbeb904be2985Evgeniy Stepanov#if LLVM_ON_UNIX && !defined(__ANDROID__)
5395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  char MyHostname[256];
5495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  MyHostname[255] = 0;
5595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  MyHostname[0] = 0;
5695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  gethostname(MyHostname, 255);
5795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Check whether the process is dead. If so, we're done.
5895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (MyHostname == Hostname && getsid(PID) == -1 && errno == ESRCH)
5995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return false;
6095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
6195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
6295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  return true;
6395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor}
6495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
6595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas GregorLockFileManager::LockFileManager(StringRef FileName)
6695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor{
6795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  LockFileName = FileName;
6895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  LockFileName += ".lock";
6995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
7095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // If the lock file already exists, don't bother to try to create our own
7195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // lock file; it won't work anyway. Just figure out who owns this lock file.
7295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if ((Owner = readLockFile(LockFileName)))
7395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return;
7495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
7595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Create a lock file that is unique to this instance.
7695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  UniqueLockFileName = LockFileName;
7795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  UniqueLockFileName += "-%%%%%%%%";
7895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  int UniqueLockFileID;
7995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (error_code EC
8095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor        = sys::fs::unique_file(UniqueLockFileName.str(),
8195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor                                     UniqueLockFileID,
8295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor                                     UniqueLockFileName,
8395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor                                     /*makeAbsolute=*/false)) {
8495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    Error = EC;
8595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return;
8695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  }
8795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
8895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Write our process ID to our unique lock file.
8995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  {
9095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true);
9195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
9295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#if LLVM_ON_UNIX
9395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    // FIXME: move getpid() call into LLVM
9495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    char hostname[256];
9595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    hostname[255] = 0;
9695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    hostname[0] = 0;
9795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    gethostname(hostname, 255);
9895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    Out << hostname << ' ' << getpid();
9995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#else
10095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    Out << "localhost 1";
10195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
10295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    Out.close();
10395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
10495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    if (Out.has_error()) {
10595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      // We failed to write out PID, so make up an excuse, remove the
10695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      // unique lock file, and fail.
10795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      Error = make_error_code(errc::no_space_on_device);
10895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      bool Existed;
10995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      sys::fs::remove(UniqueLockFileName.c_str(), Existed);
11095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      return;
11195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    }
11295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  }
11395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
11495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Create a hard link from the lock file name. If this succeeds, we're done.
11595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  error_code EC
11695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    = sys::fs::create_hard_link(UniqueLockFileName.str(),
11795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor                                      LockFileName.str());
11895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (EC == errc::success)
11995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return;
12095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
12195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Creating the hard link failed.
12295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
12395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#ifdef LLVM_ON_UNIX
12495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // The creation of the hard link may appear to fail, but if stat'ing the
12595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // unique file returns a link count of 2, then we can still declare success.
12695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  struct stat StatBuf;
12795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (stat(UniqueLockFileName.c_str(), &StatBuf) == 0 &&
12895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      StatBuf.st_nlink == 2)
12995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return;
13095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
13195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
13295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Someone else managed to create the lock file first. Wipe out our unique
13395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // lock file (it's useless now) and read the process ID from the lock file.
13495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  bool Existed;
13595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  sys::fs::remove(UniqueLockFileName.str(), Existed);
13695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if ((Owner = readLockFile(LockFileName)))
13795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return;
13895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
13995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // There is a lock file that nobody owns; try to clean it up and report
14095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // an error.
14195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  sys::fs::remove(LockFileName.str(), Existed);
14295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  Error = EC;
14395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor}
14495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
14595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas GregorLockFileManager::LockFileState LockFileManager::getState() const {
14695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (Owner)
14795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return LFS_Shared;
14895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
14995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (Error)
15095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return LFS_Error;
15195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
15295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  return LFS_Owned;
15395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor}
15495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
15595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas GregorLockFileManager::~LockFileManager() {
15695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (getState() != LFS_Owned)
15795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return;
15895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
15995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Since we own the lock, remove the lock file and our own unique lock file.
16095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  bool Existed;
16195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  sys::fs::remove(LockFileName.str(), Existed);
16295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  sys::fs::remove(UniqueLockFileName.str(), Existed);
16395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor}
16495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
16595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregorvoid LockFileManager::waitForUnlock() {
16695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  if (getState() != LFS_Shared)
16795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    return;
16895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
16995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#if LLVM_ON_WIN32
17095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  unsigned long Interval = 1;
17195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#else
17295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  struct timespec Interval;
17395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  Interval.tv_sec = 0;
17495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  Interval.tv_nsec = 1000000;
17595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
17695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Don't wait more than an hour for the file to appear.
17795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  const unsigned MaxSeconds = 3600;
17895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  do {
17995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    // Sleep for the designated interval, to allow the owning process time to
18095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    // finish up and remove the lock file.
18195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    // FIXME: Should we hook in to system APIs to get a notification when the
18295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    // lock file is deleted?
18395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#if LLVM_ON_WIN32
18495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    Sleep(Interval);
18595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#else
18695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    nanosleep(&Interval, NULL);
18795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
18895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    // If the file no longer exists, we're done.
18995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    bool Exists = false;
19095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists)
19195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      return;
19295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
19395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    if (!processStillExecuting((*Owner).first, (*Owner).second))
19495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      return;
19595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
19695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    // Exponentially increase the time we wait for the lock to be removed.
19795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#if LLVM_ON_WIN32
19895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    Interval *= 2;
19995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#else
20095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    Interval.tv_sec *= 2;
20195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    Interval.tv_nsec *= 2;
20295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    if (Interval.tv_nsec >= 1000000000) {
20395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      ++Interval.tv_sec;
20495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor      Interval.tv_nsec -= 1000000000;
20595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor    }
20695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
20795fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  } while (
20895fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#if LLVM_ON_WIN32
20995fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor           Interval < MaxSeconds * 1000
21095fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#else
21195fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor           Interval.tv_sec < (time_t)MaxSeconds
21295fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor#endif
21395fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor           );
21495fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor
21595fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor  // Give up.
21695fa4005f5aa99878c4053e95b230f0b8b6a4d6dDouglas Gregor}
217