Browse Source

VS: Replace generation timestamp file atomically

Since commit 34c882a9 (Allow VS 7 project Rebuild and Solution Rebuild to
work, 2007-11-10) we use a "CMakeFiles/generated.stamp" and some
associated files in the build tree to avoid re-running CMake when the
inputs have not changed but VS has cleaned the outputs it knows about.

When we do not really need to re-run we restore the generated.stamp file.
The non-re-run case can happen in multiple targets in parallel in VS >= 10
so we must restore the file atomically to avoid races.  Write the stamp
file to a random temporary name and then atomically rename it to the real
stamp file.
Brad King 12 years ago
parent
commit
2dc17f88dd
1 changed files with 12 additions and 3 deletions
  1. 12 3
      Source/cmake.cxx

+ 12 - 3
Source/cmake.cxx

@@ -4033,10 +4033,18 @@ static bool cmakeCheckStampFile(const char* stampName)
     }
 
   // The build system is up to date.  The stamp file has been removed
-  // by the VS IDE due to a "rebuild" request.  Just restore it.
-  std::ofstream stamp(stampName);
+  // by the VS IDE due to a "rebuild" request.  Restore it atomically.
+  cmOStringStream stampTempStream;
+  stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
+  std::string stampTempString = stampTempStream.str();
+  const char* stampTemp = stampTempString.c_str();
+  {
+  // TODO: Teach cmGeneratedFileStream to use a random temp file (with
+  // multiple tries in unlikely case of conflict) and use that here.
+  std::ofstream stamp(stampTemp);
   stamp << "# CMake generation timestamp file this directory.\n";
-  if(stamp)
+  }
+  if(cmSystemTools::RenameFile(stampTemp, stampName))
     {
     // Notify the user why CMake is not re-running.  It is safe to
     // just print to stdout here because this code is only reachable
@@ -4047,6 +4055,7 @@ static bool cmakeCheckStampFile(const char* stampName)
     }
   else
     {
+    cmSystemTools::RemoveFile(stampTemp);
     cmSystemTools::Error("Cannot restore timestamp ", stampName);
     return false;
     }