Browse Source

Merge topic 'windows-filesystem-retry-config'

7b1f966a Windows: Make file delete/rename retry configurable
Brad King 11 years ago
parent
commit
b486c6d49a
3 changed files with 60 additions and 8 deletions
  1. 9 4
      Source/cmCoreTryCompile.cxx
  2. 42 4
      Source/cmSystemTools.cxx
  3. 9 0
      Source/cmSystemTools.h

+ 9 - 4
Source/cmCoreTryCompile.cxx

@@ -585,15 +585,20 @@ void cmCoreTryCompile::CleanupFiles(const char* binDir)
           }
         else
           {
+#ifdef _WIN32
           // Sometimes anti-virus software hangs on to new files so we
           // cannot delete them immediately.  Try a few times.
-          int tries = 5;
+          cmSystemTools::WindowsFileRetry retry =
+            cmSystemTools::GetWindowsFileRetry();
           while(!cmSystemTools::RemoveFile(fullPath.c_str()) &&
-                --tries && cmSystemTools::FileExists(fullPath.c_str()))
+                --retry.Count && cmSystemTools::FileExists(fullPath.c_str()))
             {
-            cmSystemTools::Delay(500);
+            cmSystemTools::Delay(retry.Delay);
             }
-          if(tries == 0)
+          if(retry.Count == 0)
+#else
+          if(!cmSystemTools::RemoveFile(fullPath.c_str()))
+#endif
             {
             std::string m = "Remove failed on file: " + fullPath;
             cmSystemTools::ReportLastSystemError(m.c_str());

+ 42 - 4
Source/cmSystemTools.cxx

@@ -863,6 +863,44 @@ bool cmSystemTools::CopyFileIfDifferent(const char* source,
   return Superclass::CopyFileIfDifferent(source, destination);
 }
 
+//----------------------------------------------------------------------------
+#ifdef _WIN32
+cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry()
+{
+  static WindowsFileRetry retry = {0,0};
+  if(!retry.Count)
+    {
+    unsigned int data[2] = {0,0};
+    HKEY const keys[2] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE};
+    wchar_t const* const values[2] = {L"FilesystemRetryCount",
+                                      L"FilesystemRetryDelay"};
+    for(int k=0; k < 2; ++k)
+      {
+      HKEY hKey;
+      if(RegOpenKeyExW(keys[k], L"Software\\Kitware\\CMake\\Config",
+                       0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+        {
+        for(int v=0; v < 2; ++v)
+          {
+          DWORD dwData, dwType, dwSize = 4;
+          if(!data[v] &&
+             RegQueryValueExW(hKey, values[v], 0, &dwType, (BYTE *)&dwData,
+                              &dwSize) == ERROR_SUCCESS &&
+             dwType == REG_DWORD && dwSize == 4)
+            {
+            data[v] = static_cast<unsigned int>(dwData);
+            }
+          }
+        RegCloseKey(hKey);
+        }
+      }
+    retry.Count = data[0]? data[0] : 5;
+    retry.Delay = data[1]? data[1] : 500;
+    }
+  return retry;
+}
+#endif
+
 //----------------------------------------------------------------------------
 bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
 {
@@ -874,10 +912,10 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
      fails then remove the read-only attribute from any existing destination.
      Try multiple times since we may be racing against another process
      creating/opening the destination file just before our MoveFileEx.  */
-  int tries = 5;
+  WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry();
   while(!MoveFileExW(cmsys::Encoding::ToWide(oldname).c_str(),
                      cmsys::Encoding::ToWide(newname).c_str(),
-                     MOVEFILE_REPLACE_EXISTING) && --tries)
+                     MOVEFILE_REPLACE_EXISTING) && --retry.Count)
     {
     // Try again only if failure was due to access permissions.
     if(GetLastError() != ERROR_ACCESS_DENIED)
@@ -896,10 +934,10 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
     else
       {
       // The file may be temporarily in use so wait a bit.
-      cmSystemTools::Delay(100);
+      cmSystemTools::Delay(retry.Delay);
       }
     }
-  return tries > 0;
+  return retry.Count > 0;
 #else
   /* On UNIX we have an OS-provided call to do this atomically.  */
   return rename(oldname, newname) == 0;

+ 9 - 0
Source/cmSystemTools.h

@@ -460,6 +460,15 @@ public:
   /** Tokenize a string */
   static std::vector<std::string> tokenize(const std::string& str,
                                            const std::string& sep);
+
+#ifdef _WIN32
+  struct WindowsFileRetry
+  {
+    unsigned int Count;
+    unsigned int Delay;
+  };
+  static WindowsFileRetry GetWindowsFileRetry();
+#endif
 private:
   static bool s_ForceUnixPaths;
   static bool s_RunCommandHideConsole;