Skip to main content
Glama
GOROUTINE_LEAK_ANALYSIS.md3.35 kB
# Goroutine Leak Analysis for StreamableServer ## Summary Found several potential goroutine leaks in the StreamableServer implementation: ## 1. BroadcastNotification Goroutines (Line 665) **Location**: `streamable_server.go:665` ```go for _, session := range sessions { go s.sendSSEEvent(session, "message", notification) } ``` **Issue**: - Creates goroutines without tracking or cleanup - No panic recovery - No context cancellation - Could accumulate if sendSSEEvent blocks **Fix**: Use a worker pool or add timeout/context to sendSSEEvent ## 2. setupEventBroadcasting Goroutine (Line 711) **Location**: `streamable_server.go:711` ```go go s.setupEventBroadcasting() ``` **Issue**: - Started in Start() but never stopped - Subscribes to events but doesn't unsubscribe - No cleanup mechanism when server stops **Fix**: Add proper cleanup in Stop() method ## 3. Process Monitoring Goroutine in tools.go (Line 216) **Location**: `tools.go:216-224` ```go go func() { for { time.Sleep(100 * time.Millisecond) if process.Status != "running" { close(logChan) break } } }() ``` **Issue**: - No panic recovery - Polling instead of event-driven - No context cancellation - Could leak if process status tracking fails **Fix**: Use context cancellation and panic recovery ## 4. Connection Manager Goroutines **Location**: `connection_manager.go` ### 4.1 monitorConnections (Line 150) ```go go cm.monitorConnections() ``` **Issue**: - Started in run() but cleanup depends on stopCh - No panic recovery ### 4.2 attemptConnection (Lines 420, 427) ```go go cm.attemptConnection(info.InstanceID) ``` **Issue**: - Spawned without tracking - No timeout context for the entire operation - Could accumulate if connections hang ## 5. Missing Cleanup in handleStreamingConnection **Location**: `streamable_server.go:375-507` **Issues**: - Event subscriptions don't get unsubscribed on disconnect - Resource update handler registration but cleanup only in defer - Channel cleanup could be improved ## 6. Channel Leaks **Location**: Various - `eventChan` and `resourceUpdateChan` in handleStreamingConnection - `logChan` in tools.go streaming handler - REPL response channels in `replResponseChans` map **Issue**: Channels might not be properly closed/drained in all error paths ## Recommendations 1. **Add Panic Recovery**: Wrap all goroutines with defer/recover 2. **Use Context**: Pass context.Context to all goroutines for cancellation 3. **Track Goroutines**: Use sync.WaitGroup or similar for tracking 4. **Proper Cleanup**: Ensure Stop() method cleans up all resources 5. **Event Unsubscribe**: Track and unsubscribe all event subscriptions 6. **Timeout Operations**: Add timeouts to blocking operations 7. **Worker Pools**: Use bounded worker pools instead of spawning unlimited goroutines ## Example Fix Pattern ```go func (s *StreamableServer) safeGo(ctx context.Context, fn func()) { s.wg.Add(1) go func() { defer s.wg.Done() defer func() { if r := recover(); r != nil { s.logStore.Add("mcp-server", "ERROR", fmt.Sprintf("Panic in goroutine: %v", r), true) } }() select { case <-ctx.Done(): return default: fn() } }() } ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/standardbeagle/brummer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server