summaryrefslogtreecommitdiffstats
path: root/Source/cmSystemTools.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2014-02-12 14:45:56 (GMT)
committerBrad King <brad.king@kitware.com>2014-02-12 14:55:41 (GMT)
commit7b1f966a6c456270004a2aec2c53057ca8efbac9 (patch)
tree9ac334c91b0a8a501ef34350bf8675cd5ce6f719 /Source/cmSystemTools.cxx
parent5104f55d3f9cf2f9b2537364d1b9a5c86d2f790b (diff)
downloadCMake-7b1f966a6c456270004a2aec2c53057ca8efbac9.zip
CMake-7b1f966a6c456270004a2aec2c53057ca8efbac9.tar.gz
CMake-7b1f966a6c456270004a2aec2c53057ca8efbac9.tar.bz2
Windows: Make file delete/rename retry configurable
Several CMake operations need to replace files in rapid succession. This commonly fails on Windows due to filesystem lock behavior so we have retry loops. No matter how many times we retry or how long we delay there will inevitably be someone with an environment that needs more. Make the retry count and delay configurable in the Windows Registry keys: {HKCU,HKLM}/Software/Kitware/CMake/Config in DWORD values FilesystemRetryCount = Number of tries FilesystemRetryDelay = Delay in milliseconds between tries Leave the feature undocumented for now to see how it goes.
Diffstat (limited to 'Source/cmSystemTools.cxx')
-rw-r--r--Source/cmSystemTools.cxx46
1 files changed, 42 insertions, 4 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 41c7509..ff05975 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -864,6 +864,44 @@ bool cmSystemTools::CopyFileIfDifferent(const char* source,
}
//----------------------------------------------------------------------------
+#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)
{
#ifdef _WIN32
@@ -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;