[cfe-commits] r136315 - in /cfe/trunk: include/clang/Frontend/CompilerInstance.h lib/Frontend/ASTUnit.cpp lib/Frontend/CompilerInstance.cpp lib/Frontend/FrontendActions.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Wed Jul 27 17:45:10 PDT 2011


Author: akirtzidis
Date: Wed Jul 27 19:45:10 2011
New Revision: 136315

URL: http://llvm.org/viewvc/llvm-project?rev=136315&view=rev
Log:
Cut down the number of open/close system calls for output files.

For PCH files, have only one open/close for temporary + rename to be safe from race conditions.
For all other output files open/close the output file directly.

Depends on llvm r136310. rdar://9082880 & http://llvm.org/PR9374.

Modified:
    cfe/trunk/include/clang/Frontend/CompilerInstance.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Frontend/FrontendActions.cpp

Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=136315&r1=136314&r2=136315&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original)
+++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Wed Jul 27 19:45:10 2011
@@ -570,14 +570,16 @@
   createOutputFile(StringRef OutputPath,
                    bool Binary = true, bool RemoveFileOnSignal = true,
                    StringRef BaseInput = "",
-                   StringRef Extension = "");
+                   StringRef Extension = "",
+                   bool UseTemporary = false);
 
   /// Create a new output file, optionally deriving the output path name.
   ///
   /// If \arg OutputPath is empty, then createOutputFile will derive an output
   /// path location as \arg BaseInput, with any suffix removed, and \arg
-  /// Extension appended. If OutputPath is not stdout createOutputFile will
-  /// create a new temporary file that must be renamed to OutputPath in the end.
+  /// Extension appended. If OutputPath is not stdout and \arg UseTemporary
+  /// is true, createOutputFile will create a new temporary file that must be
+  /// renamed to OutputPath in the end.
   ///
   /// \param OutputPath - If given, the path to the output file.
   /// \param Error [out] - On failure, the error message.
@@ -588,6 +590,8 @@
   /// \param RemoveFileOnSignal - Whether the file should be registered with
   /// llvm::sys::RemoveFileOnSignal. Note that this is not safe for
   /// multithreaded use, as the underlying signal mechanism is not reentrant
+  /// \param UseTemporary - Create a new temporary file that must be renamed to
+  ///         OutputPath in the end
   /// \param ResultPathName [out] - If given, the result path name will be
   /// stored here on success.
   /// \param TempPathName [out] - If given, the temporary file path name
@@ -597,6 +601,7 @@
                    bool Binary = true, bool RemoveFileOnSignal = true,
                    StringRef BaseInput = "",
                    StringRef Extension = "",
+                   bool UseTemporary = false,
                    std::string *ResultPathName = 0,
                    std::string *TempPathName = 0);
 

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=136315&r1=136314&r2=136315&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Wed Jul 27 19:45:10 2011
@@ -2309,23 +2309,17 @@
 
   // Write to a temporary file and later rename it to the actual file, to avoid
   // possible race conditions.
-  llvm::sys::Path TempPath(File);
-  if (TempPath.makeUnique(/*reuse_current=*/false, /*ErrMsg*/0))
+  llvm::SmallString<128> TempPath;
+  TempPath = File;
+  TempPath += "-%%%%%%%%";
+  int fd;
+  if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
+                                 /*makeAbsolute=*/false))
     return CXSaveError_Unknown;
-  // makeUnique may or may not have created the file. Try deleting before
-  // opening so that we can use F_Excl for exclusive access.
-  TempPath.eraseFromDisk();
 
   // FIXME: Can we somehow regenerate the stat cache here, or do we need to 
   // unconditionally create a stat cache when we parse the file?
-  std::string ErrorInfo;
-  llvm::raw_fd_ostream Out(TempPath.c_str(), ErrorInfo,
-                           llvm::raw_fd_ostream::F_Binary |
-                           // if TempPath already exists, we should not try to
-                           // overwrite it, we want to avoid race conditions.
-                           llvm::raw_fd_ostream::F_Excl);
-  if (!ErrorInfo.empty() || Out.has_error())
-    return CXSaveError_Unknown;
+  llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true);
 
   serialize(Out);
   Out.close();

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=136315&r1=136314&r2=136315&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Wed Jul 27 19:45:10 2011
@@ -437,11 +437,13 @@
 CompilerInstance::createOutputFile(StringRef OutputPath,
                                    bool Binary, bool RemoveFileOnSignal,
                                    StringRef InFile,
-                                   StringRef Extension) {
+                                   StringRef Extension,
+                                   bool UseTemporary) {
   std::string Error, OutputPathName, TempPathName;
   llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
                                               RemoveFileOnSignal,
                                               InFile, Extension,
+                                              UseTemporary,
                                               &OutputPathName,
                                               &TempPathName);
   if (!OS) {
@@ -465,6 +467,7 @@
                                    bool RemoveFileOnSignal,
                                    StringRef InFile,
                                    StringRef Extension,
+                                   bool UseTemporary,
                                    std::string *ResultPathName,
                                    std::string *TempPathName) {
   std::string OutFile, TempFile;
@@ -480,8 +483,11 @@
   } else {
     OutFile = "-";
   }
-  
-  if (OutFile != "-") {
+
+  llvm::OwningPtr<llvm::raw_fd_ostream> OS;
+  std::string OSFile;
+
+  if (UseTemporary && OutFile != "-") {
     llvm::sys::Path OutPath(OutFile);
     // Only create the temporary if we can actually write to OutPath, otherwise
     // we want to fail early.
@@ -489,21 +495,26 @@
     if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) ||
         (OutPath.isRegularFile() && OutPath.canWrite())) {
       // Create a temporary file.
-      llvm::sys::Path TempPath(OutFile);
-      if (!TempPath.makeUnique(/*reuse_current=*/false, /*ErrMsg*/0))
-        TempFile = TempPath.str();
+      llvm::SmallString<128> TempPath;
+      TempPath = OutFile;
+      TempPath += "-%%%%%%%%";
+      int fd;
+      if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
+                               /*makeAbsolute=*/false) == llvm::errc::success) {
+        OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
+        OSFile = TempFile = TempPath.str();
+      }
     }
   }
 
-  std::string OSFile = OutFile;
-  if (!TempFile.empty())
-    OSFile = TempFile;
-
-  llvm::OwningPtr<llvm::raw_fd_ostream> OS(
-    new llvm::raw_fd_ostream(OSFile.c_str(), Error,
-                             (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
-  if (!Error.empty())
-    return 0;
+  if (!OS) {
+    OSFile = OutFile;
+    OS.reset(
+      new llvm::raw_fd_ostream(OSFile.c_str(), Error,
+                               (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
+    if (!Error.empty())
+      return 0;
+  }
 
   // Make sure the out stream file gets removed if we crash.
   if (RemoveFileOnSignal)

Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=136315&r1=136314&r2=136315&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Wed Jul 27 19:45:10 2011
@@ -102,8 +102,10 @@
 
   // We use createOutputFile here because this is exposed via libclang, and we
   // must disable the RemoveFileOnSignal behavior.
+  // We use a temporary to avoid race conditions.
   OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
-                           /*RemoveFileOnSignal=*/false, InFile);
+                           /*RemoveFileOnSignal=*/false, InFile,
+                           /*Extension=*/"", /*useTemporary=*/true);
   if (!OS)
     return true;
 





More information about the cfe-commits mailing list