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

   ## What
   
   `List` and `IsAvailable` read `dir.invokers` without a lock, while `Destroy` 
reassigns it under `base.Directory.mutex` (via `DoDestroy`). The unlocked reads 
race the write (data race on the slice header).
   
   ## Why
   
   ```go
   // cluster/directory/static/directory.go
   func (dir *directory) IsAvailable() bool {
       ...
       if len(dir.invokers) == 0 { ... }                 // unlocked read
       for _, invoker := range dir.invokers { ... }      // unlocked range
   }
   func (dir *directory) List(...) []protocolbase.Invoker {
       l := len(dir.invokers); ... copy(invokers, dir.invokers)  // unlocked 
read
   }
   func (dir *directory) Destroy() {
       dir.DoDestroy(func() { ...; dir.invokers = []protocolbase.Invoker{} })  
// write under base.Directory.mutex
   }
   ```
   
   `base.Directory.mutex` is unexported and not accessible from the `static` 
package, so the static directory needs its own lock for `invokers`.
   
   ## Fix
   
   Add a `sync.RWMutex` to the static `directory`:
   
   - `IsAvailable`/`List` snapshot `invokers` under `RLock` and iterate the 
snapshot.
   - `List` releases the lock **before** calling `RouterChain()` (which takes 
`base.Directory.mutex`) so the two locks never nest — no deadlock.
   - `Destroy`'s closure writes `invokers` under the new lock (inside 
`DoDestroy`, which holds `base.Directory.mutex`; no other path holds the new 
lock while waiting for `base.Directory.mutex`).
   
   ## Tests
   
   Added `TestStaticDirListVsDestroyRace`: 50 rounds of concurrent 
`List`/`IsAvailable`/`Destroy`, passing under `-race`.
   
   Fixes #3520


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