Skip to content
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: File.Readdir can return more than n #13778

Closed
dsoprea opened this issue Dec 30, 2015 · 1 comment
Closed

os: File.Readdir can return more than n #13778

dsoprea opened this issue Dec 30, 2015 · 1 comment

Comments

@dsoprea
Copy link

@dsoprea dsoprea commented Dec 30, 2015

File.Readdir takes an n parameter that specifies a maximum count to return ("If n > 0, Readdir returns at most n FileInfo structures."). However, I'm seeing more than n being returned when n is both 3 and 5 (and likely other values as well).

Channelizing the File.Readdir call:

func (self *Path) List(path string) (<-chan *os.FileInfo, <-chan bool, error) {
    entriesChannel := make(chan *os.FileInfo)
    doneChannel := make(chan bool)

    go func() {
        f, err := os.Open(path)
        if err != nil {
            panic(err)
        }

        defer f.Close()

        for {
            fmt.Printf("Batch!\n")

            entries, err := f.Readdir(PathListBatchSize)
            if err == io.EOF {
                break
            } else if err != nil {
                panic(err)
            }

            for i := range entries {
                entriesChannel <- &entries[i]
            }
        }

        doneChannel <- true
    }()

    return entriesChannel, doneChannel, nil
}

Using it:

func main() {
    p := pfinternal.NewPath()
    entriesChannel, doneChannel, err := p.List("/tmp/test_root")
    if err != nil {
        panic(err)
    }

    done := false
    for done == false {
        select {
            case entry := <-entriesChannel:
                fmt.Printf("ENTRY: %s\n", (*entry).Name())

            case done = <-doneChannel:
                break
        }
    }
}

With n = 3:

$ ./pfmain 
Batch!
ENTRY: a
ENTRY: b
Batch!
ENTRY: c
ENTRY: d
ENTRY: e
ENTRY: f
Batch!
ENTRY: g
ENTRY: h
Batch!
ENTRY: i
Batch!
ENTRY: j

With n = 5:

$ ./pfmain 
Batch!
ENTRY: a
ENTRY: b
ENTRY: c
ENTRY: d
Batch!
ENTRY: e
ENTRY: f
ENTRY: g
ENTRY: h
ENTRY: i
ENTRY: j
Batch!
@ianlancetaylor ianlancetaylor changed the title File.Readdir can return more than n os: File.Readdir can return more than n Dec 30, 2015
@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Dec 30, 2015

Your program has a race condition. There is no necessary connection between the print of "Batch!" and the print of the ENTRY lines, so there is no required order. It would be easy for you to prove your case: check the len of the value returned by Readdir directly, rather than doing it indirectly by looking at print statements.

I'm going to close this. If you are sure this is a bug, please provide a non-racy test case. Please also provide a complete standalone program, rather than portions of a larger program. Thanks.

@golang golang locked and limited conversation to collaborators Dec 29, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.