-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
os: small-count Readdirnames followed by seek-to-zero can lead to duplicate names #37161
Comments
Thank you for reporting this issue @chris3torek and welcome to the Go project! So this looks quite similar to bug #35767 that involved cached results on Darwin and that @randall77 fixed with CL https://go-review.googlesource.com/c/go/+/209961 for Go1.14. Thus: go get golang.org/dl/go1.14rc1 && go1.14rc1 run main.go b) Kindly putting this on @randall77's radar as perhaps we might need to implement the previous polyfill for func (f *File) seekInvalidate() on non-GOOS=darwin and non-GOOS=js systems. Thank you. |
Yes, looks like we need a similar fix to CL 209961 for non-darwin unix. |
Change https://golang.org/cl/219143 mentions this issue: |
I won't have a chance to try any of this for a few days at least, but the current fix looks fine and I'm certain it will work. |
Change https://golang.org/cl/221778 mentions this issue: |
Update #37161 Change-Id: Iee828bbcc8436af29ca6dd9ed897cb5265a57cf8 Reviewed-on: https://go-review.googlesource.com/c/go/+/221778 Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
I think so, since the code has not changed. (It's kind of a minor bug too...)
What operating system and processor architecture are you using (
go env
)?(I'll just include the freebsd one here - as long as the calls go through the
file_unix.go
code the OS is not particularly relevant)go env
OutputWhat did you do?
This has to be run where there is a file system with some direntries (and probably it's specific to Unix-like systems with getdirentries calls). It does reproduce even on the Go Playground though.
What did you expect to see?
Output in which file names don't repeat, in the second output line.
What did you see instead?
Output in which file names do repeat. Here's what happens in the Playground:
The root cause
The actual cause of the bug is pretty straightforward. If you use
Readdirnames
to the end of the directory, the block holdinggetdirentries
data is fully consumed, but if you call it with a small count (such as the1
in the example above), it's not. So inos/dir_unix.go
, thedirinfo
data hasd.bufp < d.nbuf
.The
Seek
function has a test in it:which makes sure that the only allowable seek on a directory is to zero, but this never clears out the
dirinfo
. So the buffered entries remain, and we get them on the next call to Readdirnames(-1)—on the Playground this istmp
etc
andusr
. Then the buffer is drained so we call the underlyinggetdirentries
system call again, filling the buffer withdev
,tmp
,etc
, andusr
, and we retrieve them, resulting in the doubled-up entries.One proposed fix would be to move
f.dirinfo
checking fromos/file.go
'sSeek
to the next level down. If seeking on a directory, check the offset-and-whence there (perhaps seeking directories to nonzero locations and/or to the end should be allowed on some systems; this could also allow relative seek by 0 bytes to return an offset, if desirable) and zap any buffered data there.The text was updated successfully, but these errors were encountered: