mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
fix(tools): use sync.Once for thread-safe Stop() in SessionManager
The Stop() method previously used a select/default pattern which was not safe under concurrent calls — two goroutines could both pass the check and attempt to close the same channel, causing a panic. Replace with sync.Once to guarantee exactly-once close semantics, matching the documented contract of being safe for concurrent use. Review feedback: afjcjsbx
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package tools
|
||||
package tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
Reference in New Issue
Block a user