]> granicus.if.org Git - clang/commitdiff
[Tooling] Restore working dir in ClangTool.
authorIlya Biryukov <ibiryukov@google.com>
Tue, 11 Sep 2018 07:29:09 +0000 (07:29 +0000)
committerIlya Biryukov <ibiryukov@google.com>
Tue, 11 Sep 2018 07:29:09 +0000 (07:29 +0000)
Summary:
And add an option to disable this behavior. The option is only used in
AllTUsExecutor to avoid races when running concurrently on multiple
threads.

This fixes PR38869 introduced by r340937.

Reviewers: ioeric, steveire

Reviewed By: ioeric

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D51864

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341910 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Tooling/Tooling.h
lib/Tooling/AllTUsExecution.cpp
lib/Tooling/Tooling.cpp

index be9ecad976070e5b5f6ab3e4ba7f70d4d29a9f9d..bbcccc589f2203ed8585b5558c6be01d29df8914 100644 (file)
@@ -356,6 +356,11 @@ public:
   /// append them to ASTs.
   int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs);
 
+  /// Sets whether working directory should be restored after calling run(). By
+  /// default, working directory is restored. However, it could be useful to
+  /// turn this off when running on multiple threads to avoid the raciness.
+  void setRestoreWorkingDir(bool RestoreCWD);
+
   /// Returns the file manager used in the tool.
   ///
   /// The file manager is shared between all translation units.
@@ -380,6 +385,8 @@ private:
   ArgumentsAdjuster ArgsAdjuster;
 
   DiagnosticConsumer *DiagConsumer = nullptr;
+
+  bool RestoreCWD = true;
 };
 
 template <typename T>
index b761556ee76b4c25526343aa30cba54e824c8b57..a7af541cc5d2d955ca163dec7fa2b289f7c992d6 100644 (file)
@@ -104,7 +104,12 @@ llvm::Error AllTUsToolExecutor::execute(
   {
     llvm::ThreadPool Pool(ThreadCount == 0 ? llvm::hardware_concurrency()
                                            : ThreadCount);
-
+    llvm::SmallString<128> InitialWorkingDir;
+    if (auto EC = llvm::sys::fs::current_path(InitialWorkingDir)) {
+      InitialWorkingDir = "";
+      llvm::errs() << "Error while getting current working directory: "
+                   << EC.message() << "\n";
+    }
     for (std::string File : Files) {
       Pool.async(
           [&](std::string Path) {
@@ -116,12 +121,19 @@ llvm::Error AllTUsToolExecutor::execute(
             for (const auto &FileAndContent : OverlayFiles)
               Tool.mapVirtualFile(FileAndContent.first(),
                                   FileAndContent.second);
+            // Do not restore working dir from multiple threads to avoid races.
+            Tool.setRestoreWorkingDir(false);
             if (Tool.run(Action.first.get()))
               AppendError(llvm::Twine("Failed to run action on ") + Path +
                           "\n");
           },
           File);
     }
+    if (!InitialWorkingDir.empty()) {
+      if (auto EC = llvm::sys::fs::set_current_path(InitialWorkingDir))
+        llvm::errs() << "Error while restoring working directory: "
+                     << EC.message() << "\n";
+    }
   }
 
   if (!ErrorMsg.empty())
index 1ec285cc47e5aa3fa1aaca74044569733866bc09..395d2d7a04d9848b83e2c533e1cc008664d679c1 100644 (file)
@@ -441,6 +441,17 @@ int ClangTool::run(ToolAction *Action) {
     AbsolutePaths.push_back(std::move(*AbsPath));
   }
 
+  // Remember the working directory in case we need to restore it.
+  std::string InitialWorkingDir;
+  if (RestoreCWD) {
+    if (auto CWD = OverlayFileSystem->getCurrentWorkingDirectory()) {
+      InitialWorkingDir = std::move(*CWD);
+    } else {
+      llvm::errs() << "Could not get working directory: "
+                   << CWD.getError().message() << "\n";
+    }
+  }
+
   for (llvm::StringRef File : AbsolutePaths) {
     // Currently implementations of CompilationDatabase::getCompileCommands can
     // change the state of the file system (e.g.  prepare generated headers), so
@@ -508,6 +519,13 @@ int ClangTool::run(ToolAction *Action) {
       }
     }
   }
+
+  if (!InitialWorkingDir.empty()) {
+    if (auto EC =
+            OverlayFileSystem->setCurrentWorkingDirectory(InitialWorkingDir))
+      llvm::errs() << "Error when trying to restore working dir: "
+                   << EC.message() << "\n";
+  }
   return ProcessingFailed ? 1 : (FileSkipped ? 2 : 0);
 }
 
@@ -544,6 +562,10 @@ int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
   return run(&Action);
 }
 
+void ClangTool::setRestoreWorkingDir(bool RestoreCWD) {
+  this->RestoreCWD = RestoreCWD;
+}
+
 namespace clang {
 namespace tooling {