Aias00 opened a new pull request, #3545:
URL: https://github.com/apache/dubbo-go/pull/3545
## What
`dataListener.interestedURL` was a plain slice with no lock;
`AddInterestedURL` appends from the `DoSubscribe` path while `DataChange` reads
it (`slices.ContainsFunc`) on the etcd watch goroutine, racing the slice header.
## Why
```go
// registry/etcdv3/listener.go (before)
type dataListener struct {
interestedURL []*common.URL // no lock
listener config_center.ConfigurationListener
}
func (l *dataListener) AddInterestedURL(url *common.URL) {
l.interestedURL = append(l.interestedURL, url) // DoSubscribe path
}
func (l *dataListener) DataChange(eventType remoting.Event) bool {
...
if slices.ContainsFunc(l.interestedURL, serviceURL.URLEqual) { // etcd
watch goroutine
l.listener.Process(...)
}
}
```
Two near-simultaneous `DoSubscribe` calls, or a subscribe concurrent with an
incoming etcd watch event, race on the slice header → torn reads, missed event
matching. `go test -race` flags it.
## Fix
Add a `sync.RWMutex` to `dataListener`. `AddInterestedURL` takes the write
lock; `DataChange` does the `ContainsFunc` check under `RLock`, releases it,
then dispatches `Process` outside the lock.
## Tests
Added `Test_dataListener_ConcurrentAddAndDataChange`: 100 rounds of
concurrent `AddInterestedURL` vs `DataChange`, passing under `-race`.
`registry/etcdv3` passes under `-race`.
Fixes #3544
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]