@@ -51,7 +51,29 @@ type PluginManager struct {
5151 // map of max cache size, keyed by plugin instance
5252 pluginCacheSizeMap map [string ]int64
5353
54- // map lock
54+ // mut protects concurrent access to plugin manager state (runningPluginMap, connectionConfigMap, etc.)
55+ //
56+ // LOCKING PATTERN TO PREVENT DEADLOCKS:
57+ // - Functions that acquire mut.Lock() and call other methods MUST only call *Internal versions
58+ // - Public methods that need locking: acquire lock → call internal version → release lock
59+ // - Internal methods: assume caller holds lock, never acquire lock themselves
60+ //
61+ // Example:
62+ // func (m *PluginManager) SomeMethod() {
63+ // m.mut.Lock()
64+ // defer m.mut.Unlock()
65+ // return m.someMethodInternal()
66+ // }
67+ // func (m *PluginManager) someMethodInternal() {
68+ // // NOTE: caller must hold m.mut lock
69+ // // ... implementation without locking ...
70+ // }
71+ //
72+ // Functions with internal/external versions:
73+ // - refreshRateLimiterTable / refreshRateLimiterTableInternal
74+ // - updateRateLimiterStatus / updateRateLimiterStatusInternal
75+ // - setRateLimiters / setRateLimitersInternal
76+ // - getPluginsWithChangedLimiters / getPluginsWithChangedLimitersInternal
5577 mut sync.RWMutex
5678
5779 // shutdown synchronization
@@ -231,23 +253,32 @@ func (m *PluginManager) doRefresh() {
231253
232254// OnConnectionConfigChanged is the callback function invoked by the connection watcher when the config changed
233255func (m * PluginManager ) OnConnectionConfigChanged (ctx context.Context , configMap connection.ConnectionConfigMap , plugins map [string ]* plugin.Plugin ) {
256+ log .Printf ("[DEBUG] OnConnectionConfigChanged: acquiring lock" )
234257 m .mut .Lock ()
235258 defer m .mut .Unlock ()
259+ log .Printf ("[DEBUG] OnConnectionConfigChanged: lock acquired" )
236260
237261 log .Printf ("[TRACE] OnConnectionConfigChanged: connections: %s plugin instances: %s" , strings .Join (utils .SortedMapKeys (configMap ), "," ), strings .Join (utils .SortedMapKeys (plugins ), "," ))
238262
263+ log .Printf ("[DEBUG] OnConnectionConfigChanged: calling handleConnectionConfigChanges" )
239264 if err := m .handleConnectionConfigChanges (ctx , configMap ); err != nil {
240265 log .Printf ("[WARN] handleConnectionConfigChanges failed: %s" , err .Error ())
241266 }
267+ log .Printf ("[DEBUG] OnConnectionConfigChanged: handleConnectionConfigChanges complete" )
242268
243269 // update our plugin configs
270+ log .Printf ("[DEBUG] OnConnectionConfigChanged: calling handlePluginInstanceChanges" )
244271 if err := m .handlePluginInstanceChanges (ctx , plugins ); err != nil {
245272 log .Printf ("[WARN] handlePluginInstanceChanges failed: %s" , err .Error ())
246273 }
274+ log .Printf ("[DEBUG] OnConnectionConfigChanged: handlePluginInstanceChanges complete" )
247275
276+ log .Printf ("[DEBUG] OnConnectionConfigChanged: calling handleUserLimiterChanges" )
248277 if err := m .handleUserLimiterChanges (ctx , plugins ); err != nil {
249278 log .Printf ("[WARN] handleUserLimiterChanges failed: %s" , err .Error ())
250279 }
280+ log .Printf ("[DEBUG] OnConnectionConfigChanged: handleUserLimiterChanges complete" )
281+ log .Printf ("[DEBUG] OnConnectionConfigChanged: about to release lock and return" )
251282}
252283
253284func (m * PluginManager ) GetConnectionConfig () connection.ConnectionConfigMap {
@@ -776,14 +807,19 @@ func (m *PluginManager) setCacheOptions(pluginClient *sdkgrpc.PluginClient) erro
776807}
777808
778809func (m * PluginManager ) setRateLimiters (pluginInstance string , pluginClient * sdkgrpc.PluginClient ) error {
810+ m .mut .RLock ()
811+ defer m .mut .RUnlock ()
812+ return m .setRateLimitersInternal (pluginInstance , pluginClient )
813+ }
814+
815+ func (m * PluginManager ) setRateLimitersInternal (pluginInstance string , pluginClient * sdkgrpc.PluginClient ) error {
816+ // NOTE: caller must hold m.mut lock (at least RLock)
779817 log .Printf ("[INFO] setRateLimiters for plugin '%s'" , pluginInstance )
780818 var defs []* sdkproto.RateLimiterDefinition
781819
782- m .mut .RLock ()
783820 for _ , l := range m .userLimiters [pluginInstance ] {
784821 defs = append (defs , RateLimiterAsProto (l ))
785822 }
786- m .mut .RUnlock ()
787823
788824 req := & sdkproto.SetRateLimitersRequest {Definitions : defs }
789825
0 commit comments