google / google/gvisor

[checklocks] Support iterators

Open
#12,176 3 comments 0 reactions 1 assignee Claimed by @uzairnawaz View on GitHub
status: help wanted type: enhancement
Dominant language
Go
Stars
19.3k
Forks
2k
Avg merge
3d 5h
Merged PRs (30d)
264

Description

### Description

Currently locked access to struct members inside a loop over an [iterator](https://pkg.go.dev/iter) is not detected correctly.

Example:
```golang
package main

import (
"strings"
"sync"
)

type Entries struct {
mu sync.Mutex
// +checklocks:mu
entries []string
}

func (e *Entries) Add(s string) {
e.mu.Lock()
defer e.mu.Unlock()

for item := range strings.SplitSeq(s, " ") {
e.entries = append(e.entries, item)
}
}
```

Error:
```
go vet -vettool=$HOME/go/bin/checklocks iter_seq_checklocks.go
# command-line-arguments
./iter_seq_checklocks.go:19:24: invalid field access, mu (&({freevar:e}.mu)) must be locked when accessing entries (locks: no locks held)
./iter_seq_checklocks.go:19:5: invalid field access, mu (&({freevar:e}.mu)) must be locked when accessing entries (locks: no locks held)
```

This works if the lock is acquired inside the loop.
```golang
func (e *Entries) Add(s string) {
for item := range strings.SplitSeq(s, " ") {
e.mu.Lock()
e.entries = append(e.entries, item)
e.mu.Unlock()
}
}
```

### Is this feature related to a specific bug?

_No response_

### Do you have a specific solution in mind?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.