Skip to content

Fix potential crash in repository cache fallback #3221

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

Merged
merged 1 commit into from
Jan 25, 2021

Conversation

neonichu
Copy link
Contributor

Motivation:

It is possible that copying from the cache fails mid-way which can lead to SwiftPM hitting a precondition in the fallback.

Modifications:

We should clear any potential leftover data before doing the fallback.

Result:

Hitting the precondition can be avoided.

rdar://73505115

It is possible that copying from the cache fails mid-way which can lead to SwiftPM hitting a precondition in the fallback. We should clear any potential leftover data before doing the fallback.

rdar://73505115
@neonichu neonichu force-pushed the fix-potential-crash-in-fallback branch from 72b6ed9 to 885218a Compare January 22, 2021 21:20
@neonichu neonichu self-assigned this Jan 22, 2021
@@ -384,6 +384,8 @@ public class RepositoryManager {
} catch {
// Fetch without populating the cache in the case of an error.
print("Skipping cache due to an error: \(error)")
// It is possible that we already created the directory before failing, so clear leftover data if present.
try fileSystem.removeFileTree(repositoryPath)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm pretty sure that this can't spuriously fail because repositoryPath is missing, but could it fail because its parent path is missing or other reason? i.e. would it be better to deal with exceptions from here or let them raise?

Copy link
Contributor

Choose a reason for hiding this comment

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

testing if it exists before deleting sounds reasonable, then raising if we can't delete otherwise we will have downstream issues?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's probably not a problem in this particular case, but in general, checking for existence first can be prone to race conditions. So a pattern that usually works well for cases like this is to just do the file system operation but to silently ignore benign problems. In this case, an ENOENT error is fine but anything else should be reported. That might be what the underlying API already does, so my question was just to confirm that semantic. I'll check the code.

Copy link
Contributor Author

@neonichu neonichu Jan 25, 2021

Choose a reason for hiding this comment

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

Today it does this:

if self.exists(path, followSymlink: false) {
    try FileManager.default.removeItem(atPath: path.pathString)
 }

So the race potential is there.

Copy link
Contributor

@abertelrud abertelrud Jan 25, 2021

Choose a reason for hiding this comment

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

That's possibly a follow-on fix down in TSC, but it looks as if the code in this particular PR is correct (up in SwiftPM). I seems like correct behavior that FileSystem.removeFileTree(repositoryPath) doesn't throw an error if the file isn't already there (much like mkdir doesn't complain if the directory is there). So the code in this PR is right but TSC could use a fix, it looks like. So I have no concerns about this PR. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think what would make the most sense is to leave this as-is but change removeFileTree in TSC to not throw on ENOENT as suggested, but for the 5.4 cherry-pick we inline the ENOENT check to reduce the surface area of the change.

@abertelrud
Copy link
Contributor

@swift-ci please smoke test

@abertelrud
Copy link
Contributor

Starting smoke tests. This would be good to get into 5.4 is possible; it definitely seems safe enough.

@tomerd tomerd merged commit d9fefd7 into swiftlang:main Jan 25, 2021
@neonichu neonichu deleted the fix-potential-crash-in-fallback branch January 27, 2021 01:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants