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

   ## What
   
   `ServiceInstancesChangedListenerImpl.OnEvent` held `lstn.mutex` across the 
consumer `NotifyAll` dispatch — a `sync.Mutex` is not reentrant, so a 
`NotifyAll` callback that re-enters `AddListenerAndNotify`/`RemoveListener` on 
the same listener self-deadlocked, and a slow/blocking consumer stalled every 
other `OnEvent` on that listener.
   
   ## Why
   
   ```go
   // registry/servicediscovery/service_instances_changed_listener_impl.go 
(before)
   func (lstn *ServiceInstancesChangedListenerImpl) OnEvent(e observer.Event) 
error {
       ...
       lstn.mutex.Lock()
       defer lstn.mutex.Unlock()
       // ... rebuild allInstances / revisionToMetadata / serviceUrls ...
       for key, notifyListener := range lstn.listeners {
           ...
           notifyListener.NotifyAll(events, func() {})   // external callback 
UNDER lock
       }
       return nil
   }
   ```
   
   `AddListenerAndNotify` and `RemoveListener` both acquire `lstn.mutex`. A 
consumer `NotifyAll` that synchronously re-subscribes (directory 
re-subscription on notification) re-enters `AddListenerAndNotify` → `Lock` on 
an already-held (same-goroutine) mutex → deadlock. Independently, holding the 
lock across an external callback serializes all instance-change processing 
behind the slowest consumer. This is the same class of issue the reviewer 
flagged on PR #3442 (do not hold a registry lock across external calls). The 
sibling `AddListenerAndNotify` already snapshots under the lock and notifies 
outside; `OnEvent` did not.
   
   ## Fix
   
   Snapshot `(notifyListener, events)` pairs under `lstn.mutex`, explicitly 
`Unlock()`, then dispatch `NotifyAll` outside the lock. There is no early 
`return` between `Lock` and the explicit `Unlock` (the build loop uses 
`continue`, not `return`), so the mutex is not leaked.
   
   ## Tests
   
   Added `TestOnEvent_NoDeadlockOnReentrantNotify`: a `NotifyAll` callback that 
re-enters `AddListenerAndNotify` on the same listener. Verified it deadlocks 
(2s timeout) on the old code and passes on the fixed code. `servicediscovery` 
package passes under `-race`.
   
   Fixes #3528


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