diff options
author | Brad King <brad.king@kitware.com> | 2022-11-17 18:27:21 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2022-11-17 20:05:07 (GMT) |
commit | efa9eec0402adacc7ac8b0dc17660a8bd968b06a (patch) | |
tree | 4faf3121039e17ea3d951912b2aede27ef939f1e /Source/cmSystemTools.cxx | |
parent | fa518188d8aeffa176109bc960173b06fa1e135e (diff) | |
download | CMake-efa9eec0402adacc7ac8b0dc17660a8bd968b06a.zip CMake-efa9eec0402adacc7ac8b0dc17660a8bd968b06a.tar.gz CMake-efa9eec0402adacc7ac8b0dc17660a8bd968b06a.tar.bz2 |
file(COPY_FILE): Add option to retry on Windows if input access fails
On Windows, a file may be inaccessible for a short time after it is
created. This occurs for various reasons, including indexing, antivirus
tools, and NTFS's asynchronous semantics. Add an `INPUT_MAY_BE_RECENT`
option to tell CMake that the input file may have been recently created
so that we can retry a few times to read it.
Diffstat (limited to 'Source/cmSystemTools.cxx')
-rw-r--r-- | Source/cmSystemTools.cxx | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 75b7668..f94c4d3 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1113,7 +1113,7 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname, cmSystemTools::CopyResult cmSystemTools::CopySingleFile( std::string const& oldname, std::string const& newname, CopyWhen when, - std::string* err) + CopyInputRecent inputRecent, std::string* err) { switch (when) { case CopyWhen::Always: @@ -1137,7 +1137,24 @@ cmSystemTools::CopyResult cmSystemTools::CopySingleFile( status = cmsys::SystemTools::CloneFileContent(oldname, newname); if (!status) { // if cloning did not succeed, fall back to blockwise copy +#ifdef _WIN32 + if (inputRecent == CopyInputRecent::Yes) { + // Windows sometimes locks a file immediately after creation. + // Retry a few times. + WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry(); + while ((status = + cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname), + status.Path == cmsys::SystemTools::CopyStatus::SourcePath && + status.GetPOSIX() == EACCES && --retry.Count)) { + cmSystemTools::Delay(retry.Delay); + } + } else { + status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname); + } +#else + static_cast<void>(inputRecent); status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname); +#endif } if (!status) { if (err) { |