Merge topic 'windows-filesystem-retry-config'

7b1f966a Windows: Make file delete/rename retry configurable
This commit is contained in:
Brad King 2014-02-17 10:03:11 -05:00 committed by CMake Topic Stage
commit b486c6d49a
3 changed files with 60 additions and 8 deletions

View File

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

View File

@ -863,6 +863,44 @@ bool cmSystemTools::CopyFileIfDifferent(const char* source,
return Superclass::CopyFileIfDifferent(source, destination); 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) 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. fails then remove the read-only attribute from any existing destination.
Try multiple times since we may be racing against another process Try multiple times since we may be racing against another process
creating/opening the destination file just before our MoveFileEx. */ creating/opening the destination file just before our MoveFileEx. */
int tries = 5; WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry();
while(!MoveFileExW(cmsys::Encoding::ToWide(oldname).c_str(), while(!MoveFileExW(cmsys::Encoding::ToWide(oldname).c_str(),
cmsys::Encoding::ToWide(newname).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. // Try again only if failure was due to access permissions.
if(GetLastError() != ERROR_ACCESS_DENIED) if(GetLastError() != ERROR_ACCESS_DENIED)
@ -896,10 +934,10 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
else else
{ {
// The file may be temporarily in use so wait a bit. // 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 #else
/* On UNIX we have an OS-provided call to do this atomically. */ /* On UNIX we have an OS-provided call to do this atomically. */
return rename(oldname, newname) == 0; return rename(oldname, newname) == 0;

View File

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