Commit cf826bf
go/types, types2: set t.underlying exactly once in resolveUnderlying
While the locking in Named.resolveUnderlying is mostly fine, we do not
perform an atomic read before the write to underlying.
If resolveUnderlying returns and another thread was waiting on the lock,
it can perform a second (in this case identical) write to t.underlying.
A reader thread on n.underlying can thus observe either of those writes,
tripping the race detector.
Michael was kind enough to provide a diagram:
T1 T2
1. t.stateHas(underlying) // false
2. t.stateHas(underlying) // false
3. t.mu.Lock() // acquired
4. t.mu.Lock() // blocked
5. t.underlying = u
6. t.setState(underlying)
7. t.mu.Unlock()
8. t.underlying = u // overwritten
9. t.setState(underlying)
10. t.mu.Unlock()
Adding a second check before setting t.underlying prevents the write on
line 8.
Change-Id: Ia43a6d3ba751caef436b9926c6ece2a71dfb9d38
Reviewed-on: https://go-review.googlesource.com/c/go/+/714300
Auto-Submit: Mark Freeman <[email protected]>
Reviewed-by: Michael Pratt <[email protected]>
Reviewed-by: Robert Griesemer <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>1 parent c4e9108 commit cf826bf
2 files changed
+14
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
630 | 630 | | |
631 | 631 | | |
632 | 632 | | |
| 633 | + | |
633 | 634 | | |
634 | 635 | | |
635 | 636 | | |
| |||
640 | 641 | | |
641 | 642 | | |
642 | 643 | | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
643 | 650 | | |
644 | 651 | | |
645 | 652 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments