diff --git a/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/dataproxy/discoverer.go b/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/dataproxy/discoverer.go index 5356777ee82..640bfc62395 100755 --- a/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/dataproxy/discoverer.go +++ b/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/dataproxy/discoverer.go @@ -158,10 +158,20 @@ func (d *dataProxyDiscoverer) lookup() { d.log.Infof("update server endpoint list %s: %v", d.url, allEndpointAddrStr) } - d.RLock() - defer d.RUnlock() if len(addEndpoints) > 0 || len(delEndpoints) > 0 { + // Copy the handler list while holding the lock, then invoke callbacks after + // releasing it, to avoid calling external code while holding the lock: if a + // handler calls back into AddEventHandler/DelEventHandler/GetEndpoints + // (which need Lock/RLock) from within OnEndpointUpdate, the same goroutine + // re-entering the RWMutex would deadlock + d.RLock() + handlers := make([]discoverer.EventHandler, 0, len(d.eventHandlers)) for h := range d.eventHandlers { + handlers = append(handlers, h) + } + d.RUnlock() + + for _, h := range handlers { h.OnEndpointUpdate(allEndpoints, addEndpoints, delEndpoints) } } diff --git a/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/discoverer/dns.go b/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/discoverer/dns.go index 7abaf973936..2aa3fc11f61 100755 --- a/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/discoverer/dns.go +++ b/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/discoverer/dns.go @@ -186,10 +186,20 @@ func (d *dnsDiscoverer) lookup() { d.log.Infof("update domain host list %s: %v", d.domain, allHostStr) } - d.RLock() - defer d.RUnlock() if len(addEndpoints) > 0 || len(delEndpoints) > 0 { + // Copy the handler list while holding the lock, then invoke callbacks after + // releasing it, to avoid calling external code while holding the lock: if a + // handler calls back into AddEventHandler/DelEventHandler/GetEndpoints + // (which need Lock/RLock) from within OnEndpointUpdate, the same goroutine + // re-entering the RWMutex would deadlock + d.RLock() + handlers := make([]EventHandler, 0, len(d.eventHandlers)) for h := range d.eventHandlers { + handlers = append(handlers, h) + } + d.RUnlock() + + for _, h := range handlers { h.OnEndpointUpdate(allEndpoints, addEndpoints, delEndpoints) } }