-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue8273 corrupt nu get cache #8275
Issue8273 corrupt nu get cache #8275
Conversation
35b3ddd
to
c88d6a3
Compare
I opened dotnet/runtime#80832 Jozkee labeled it 'bug', so I'm guessing this is a runtime bug rather than an MSBuild bug. He also noted that File.Move does not have the same issue. People using MSBuild's Copy often don't care whether the source file exists afterwards, but we can't guarantee that, so I don't think we can use File.Move, unfortunately. We're still talking internally about whether we want to:
What happens on .NET Framework (and older .NET Core) may be an important question, but I haven't tested that yet. Sorry we're being a bit slow; I just wanted to give you something of an update 🙂 |
It looks like runtime isn't planning to change anything in the immediate future. We're thinking we will likely take this, but our primary concern is performance. @rokonec volunteered to take a quick look into that to see if he can find anything problematic. Additionally, would you mind putting this behind a change wave? That will turn it on by default for all users but provide a way for users to opt out should they hit perf problems. |
@@ -324,41 +329,28 @@ private void LogDiagnostic(string message, params object[] messageArgs) | |||
Log.LogMessage(MessageImportance.Normal, FileComment, sourceFilePath, destinationFilePath); | |||
|
|||
File.Copy(sourceFileState.Name, destinationFileState.Name, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the destination is always deleted, I think it would be a good idea to set the overwrite
flag to false
to protect us from accidental overwrites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is probably better to fail in case someone gets in between than overwriting a link. I will update the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not believe it is necessary. Sometimes logic might change to not delete it, or new Copy task argument will be introduced, or some weird concurrent logic is relaying with last win. I would recommend to keep it as is, but if you decide to change it, it has to go under same ChangeWave or same conditions as deleting files.
Ping @rokonec |
FWIW, I've run some benchmarks (building a large solution, with and without a change from this PR), and here are my conclusions:
Tested solution:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have spent some time to measure it and although it is very slightly slower, it is, IMO, acceptable. It took less then 0.1 % on my tests.
I went away and created some minor suggestions...
Good job.
Co-authored-by: Roman Konecny <rokonecn@microsoft.com>
0cdf3d7
to
cb5d0de
Compare
Co-authored-by: Roman Konecny <rokonecn@microsoft.com>
@rokonec I have applied your changes and rebased the branch on current main branch. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
// If the destination file is a hard or symbolic link, File.Copy would overwrite the source. | ||
// To prevent this, we need to delete the existing entry before we Copy or create a link. | ||
// We could try to figure out if the file is a link, but I can't think of a reason to not simply delete it always. | ||
if (ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_6) && destinationFileState.FileExists && !destinationFileState.IsReadOnly) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also take into account OverwriteReadOnlyFiles and also delete them in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if OverwriteReadOnlyFiles
is set, the file is made writable and hence deleted here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and now I see it 6 lines up. Stupid question, thanks!
Fixes dotnet#8273 Context Prevent overwriting the source of a hard/symbolic link. Changes Made Always delete the destination file (unless readonly and OverwriteReadOnlyFiles is false) Testing Added unit test.
This reverts commit a93882f.
This reverts commit a93882f. This is a temporary fix for #8684 The current plan is to revert #8275 in 17.6, as it caused some difficulties, and try to bring it back in 17.7 via #8685. Summary #8275 fixed a longstanding confusing and unfortunate behavior in MSBuild in which passing the Copy task a symlink as its destination would copy the source file onto the destination of the symlink rather than overwriting the symlink. Unfortunately, it also introduced a new issue in which copying a file onto itself could often just delete the file instead of copying anything. Customers reported this issue. Customer Impact Projects that copy a file onto itself using the Copy task without passing identical paths for source and destination instead delete the file without necessarily even logging an error. Regression? Yes, from #8275. Testing Unit tests and manually tested that the repro described in #8684 no longer works. Risk Minimal (straight revert of the commit that caused the bug) --------- Co-authored-by: Forgind <Forgind@users.noreply.github.com>
Fixes #8684 Fixes #8273 Context After #8275, we delete any destination file as part of the Copy task if we determine that we really should copy onto it. Unfortunately, if we try to copy a file onto itself, we delete it before we can copy onto itself, which just means it's gone. Fortunately, we have a check earlier that ensures that we skip any copy operation from a location to the same location. Unfortunately, it's a direct string comparison that doesn't evaluate to full paths first, so it misses slightly more complicated examples. Changes Made Take into account full paths Testing Unit tests + manual test that it doesn't delete the file anymore Notes This implementation tries to remove now-unnecessary full path derivations downstream, hence some added complexity, but it still means extra computation on the happy path if we end up creating a hard/symbolic link. An alternate direction eliminating any full path derivations on the happy path would save about 4% of Copy's execution time, per a quick perf test. (With how many samples I used, "no change" is within a standard deviation.)
Fixes #8273
Context
Prevent overwriting the source of a hard/symbolic link.
Changes Made
Always delete the destination file (unless readonly and OverwriteReadOnlyFiles is false)
Testing
Added unit test.
Notes