diff --git a/pkg/tools/session.go b/pkg/tools/session.go index 65aa924fd..2b03df350 100644 --- a/pkg/tools/session.go +++ b/pkg/tools/session.go @@ -172,6 +172,7 @@ type SessionManager struct { mu sync.RWMutex sessions map[string]*ProcessSession stopCh chan struct{} + stopOnce sync.Once } func NewSessionManager() *SessionManager { @@ -197,16 +198,13 @@ func NewSessionManager() *SessionManager { return sm } -// Stop shuts down the background cleanup goroutine. Safe to call multiple times. -// After Stop returns, the SessionManager is still usable — only the cleanup -// goroutine is terminated. +// Stop shuts down the background cleanup goroutine. Safe to call multiple +// times from concurrent goroutines. After Stop returns, the SessionManager +// is still usable — only the cleanup goroutine is terminated. func (sm *SessionManager) Stop() { - select { - case <-sm.stopCh: - // already closed - default: + sm.stopOnce.Do(func() { close(sm.stopCh) - } + }) } // cleanupOldSessions removes sessions that are done and older than 30 minutes diff --git a/pkg/tools/shell_test.go b/pkg/tools/shell_test.go index 4ad1f4ee8..83807dac6 100644 --- a/pkg/tools/shell_test.go +++ b/pkg/tools/shell_test.go @@ -1,4 +1,4 @@ -package tools +package tools import ( "context"