Aias00 opened a new pull request, #3517:
URL: https://github.com/apache/dubbo-go/pull/3517

   ## What
   
   The Zookeeper / etcdv3 / Nacos service-discovery backends read 
`instanceListenerMap[serviceName]` inside their watcher/subscription callbacks 
**without holding the lock** that `AddListener` / `registerInstanceListener` / 
`Destroy` mutate it under. Concurrent subscribe/unsubscribe therefore triggers 
a fatal `concurrent map read and map write`.
   
   ## Why
   
   - **zookeeper** `registry/zookeeper/service_discovery.go:279` — `DataChange` 
iterates `zksd.instanceListenerMap[serviceName].Values()` with no `listenLock`, 
while `AddListener` (`:238`) and (via `Destroy`) mutate the map under 
`listenLock`.
   - **etcdv3** `registry/etcdv3/service_discovery.go:290` — `DataChange` reads 
`e.instanceListenerMap[...]` with no `initLock`, while 
`registerServiceInstanceListener`/`registerServiceWatcher` write under 
`initLock`. Additionally, the decode-error path blanked `ServiceName` to `""` 
and then looked up `instanceListenerMap[""]` — a silent no-op rather than a 
real failure.
   - **nacos** `registry/nacos/service_discovery.go:320` — the 
`SubscribeCallback` reads `n.instanceListenerMap[serviceName]` with no 
`listenerLock`, while `registerInstanceListener` and `Destroy` mutate it under 
`listenerLock`; an in-flight callback delivered after `Destroy` clears the map 
is a live race.
   
   (`gxset.HashSet.Values()` does not panic on a nil receiver, so the issue is 
the concurrent map access, not a nil deref.)
   
   ## Fix
   
   Snapshot the listener set under the writer lock, then iterate the snapshot 
**outside** the lock to dispatch — this both eliminates the race and stops a 
slow `OnEvent` from blocking every other listener:
   
   - **zookeeper** `DataChange`: snapshot under `listenLock` via a new 
`snapshotListeners` helper; dispatch outside the lock.
   - **etcdv3** `DataChange`: snapshot under `initLock`; on decode error, log 
and `return false` instead of blanking `ServiceName`.
   - **nacos** `SubscribeCallback`: snapshot under `listenerLock` before 
`OnEvent`.
   
   ## Tests
   
   Added `TestZookeeperServiceDiscovery_SnapshotListeners` covering: missing 
key (safe no-op), present key (returns registered listeners), and concurrent 
snapshot-vs-mutation race-freedom under `-race`. `registry/zookeeper`, 
`registry/etcdv3`, `registry/nacos` all pass under `-race`.
   
   Fixes #3512


-- 
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]

Reply via email to