Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/vcpkg/base/downloads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,11 @@ namespace vcpkg
return DownloadPrognosis::OtherError;
}

fs.rename(download_path_part_path, download_path, VCPKG_LINE_INFO);
if (!fs.rename_or_delete(context, download_path_part_path, download_path).has_value())
{
return DownloadPrognosis::OtherError;
}

return DownloadPrognosis::Success;
}

Expand Down Expand Up @@ -831,7 +835,11 @@ namespace vcpkg
*out_sha512 = std::move(hash_result.hash);
}

fs.rename(download_path_part_path, download_path, VCPKG_LINE_INFO);
if (!fs.rename_or_delete(context, download_path_part_path, download_path).has_value())
{
return DownloadPrognosis::OtherError;
}

return DownloadPrognosis::Success;
}

Expand Down Expand Up @@ -865,7 +873,11 @@ namespace vcpkg

if (fs.exists(download_path_part_path, VCPKG_LINE_INFO))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This exists check is a bit suspicious given what you're already fixing here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into it and I think it's fine, though not for an obvious reason.
It's not a cross-process race. The part path here is fmt::format("{}.{}.part", ..., get_process_id()) a few lines up, so only this process can create or delete it.
It's also doing real work. rename_or_delete doesn't fail fast when the source is missing, it walks the retry loop sleeping 10ms, 100ms, 1s and 10s before giving up. So dropping the check gets you one of two bad outcomes: an ~11 second stall ending in a generic filesystem error instead of msgAssetCacheScriptFailedToWriteFile, or, if download_path happens to already exist, rename_or_delete reports a lost CAS and we return Success even though the script produced nothing.

The part I do think is off is the overload. exists(..., VCPKG_LINE_INFO) exits the process on a filesystem error, inside a function that reports everything else through context. There's no DiagnosticContext overload of exists though, only ec and LineInfo, so converting it means either swallowing the error or writing the report by hand.
Let me know if you want me to do it as part of this PR

{
fs.rename(download_path_part_path, download_path, VCPKG_LINE_INFO);
if (!fs.rename_or_delete(context, download_path_part_path, download_path).has_value())
{
return DownloadPrognosis::OtherError;
}

return DownloadPrognosis::Success;
}

Expand Down
Loading