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
cmd/go: lockedfile.File leaked in case of write error #50858
Comments
Hello! I'd like to work on this issue. To investigate this bug, I started in the My understanding of the func hashZip(mod module.Version, zipfile, ziphashfile string) error {
hash, err := dirhash.HashZip(zipfile, dirhash.DefaultHash)
if err != nil {
return err
}
if err := checkModSum(mod, hash); err != nil {
return err
}
hf, err := lockedfile.Create(ziphashfile)
if err != nil {
return err
}
if err := hf.Truncate(int64(len(hash))); err != nil {
return err
}
if _, err := hf.WriteAt([]byte(hash), 0); err != nil {
return err
}
if err := hf.Close(); err != nil {
return err
}
return nil
} if calls to My suggested fix here is to use |
@aschade92, thanks for the analysis, and I think you've got the right fix in mind for (For this specific issue I had thought that we were explicitly recording the call site in |
@bcmills do you have any suggestions about how to test the fix here? the fix itself is trivial but it is difficult to replicate in a test. What I would like to do is somehow get In lieu of other ideas, what I would do is define a method variable that tests can override so we can mock the result of |
Unfortunately I'm not sure how we could recreate the error in a test. We would need the test to successfully create and lock a file, but then fail to write to it — and that means either a full disk or a sudden disk failure. It would indeed be possible to reproduce the failure using a mock, but given that it is straight-line code I think in this case that sounds like more trouble that it is worth. (We can code-review the error paths carefully and call it a day.) |
The go modules download command has a method called hashZip which checks the hash of zip file versus an expected value, and then writes it out to a file. If the write fails though, we do not close the file leading to it being leaked. This could happen if the user runs out of disk space, causing the underlying OS write command to fail. Ultimately this led to a panic in lockfile.OpenFile which was invoked from a finalizer garbage collecting the leaked file. The result was a stack trace that didn't show the call stack from where the write failed. Fixes issue golang#50858
The go modules download command has a method called hashZip which checks the hash of a zipped directory versus an expected value, and then writes it out to a file. In the event that the write operation is not successful, we do not close the file, leading to it being leaked. This could happen if the user runs out of disk space, causing the underlying OS write command to return an error. Ultimately, this led to a panic in lockfile.OpenFile which was invoked from a finalizer garbage collecting the leaked file. The result was a stack trace that didn't show the call stack from where the write operation actually failed. Fixes issue golang#50858
Change https://go.dev/cl/383915 mentions this issue: |
The go modules download command has a method called hashZip which checks the hash of a zipped directory versus an expected value, and then writes it out to a file. In the event that the write operation is not successful, we do not close the file, leading to it being leaked. This could happen if the user runs out of disk space, causing the underlying OS write command to return an error. Ultimately, this led to a panic in lockfile.OpenFile which was invoked from a finalizer garbage collecting the leaked file. The result was a stack trace that didn't show the call stack from where the write operation actually failed. Fixes issue golang#50858
…write errors The go modules download command has a method called hashZip which checks the hash of a zipped directory versus an expected value, and then writes it out to a file. In the event that the write operation is not successful, we do not close the file, leading to it being leaked. This could happen if the user runs out of disk space, causing the underlying OS write command to return an error. Ultimately, this led to a panic in lockfile.OpenFile which was invoked from a finalizer garbage collecting the leaked file. The result was a stack trace that didn't show the call stack from where the write operation actually failed. Fixes golang#50858
…write errors The go modules download command has a method called hashZip which checks the hash of a zipped directory versus an expected value, and then writes it out to a file. In the event that the write operation is not successful, we do not close the file, leading to it being leaked. This could happen if the user runs out of disk space, causing the underlying OS write command to return an error. Ultimately, this led to a panic in lockfile.OpenFile which was invoked from a finalizer garbage collecting the leaked file. The result was a stack trace that didn't show the call stack from where the write operation actually failed. Fixes issue golang#50858
…write errors The go modules download command has a method called hashZip which checks the hash of a zipped directory versus an expected value, and then writes it out to a file. In the event that the write operation is not successful, we do not close the file, leading to it being leaked. This could happen if the user runs out of disk space, causing the underlying OS write command to return an error. Ultimately, this led to a panic in lockfile.OpenFile which was invoked from a finalizer garbage collecting the leaked file. The result was a stack trace that didn't show the call stack from where the write operation actually failed. Fixes golang#50858
Hi, I am on version 1.17.3 and I'm getting the same error on `go/pkg/mod/cache/download/rsc.io/quote/v3/@v/v3.1.0.ziphash became unreachable without a call to Close goroutine 5 [running]: |
From https://build.golang.org/log/3cbe74efe432908017a65a831f586044aaa2fa9e:
The frame printed here is supposed to be the caller of OpenFile, not OpenFile itself.
The text was updated successfully, but these errors were encountered: